diff options
Diffstat (limited to 'src/plugins/irc')
52 files changed, 2010 insertions, 526 deletions
diff --git a/src/plugins/irc/CMakeLists.txt b/src/plugins/irc/CMakeLists.txt index a5703afef..f205adbc5 100644 --- a/src/plugins/irc/CMakeLists.txt +++ b/src/plugins/irc/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # @@ -33,6 +33,7 @@ irc-info.c irc-info.h irc-input.c irc-input.h irc-message.c irc-message.h irc-mode.c irc-mode.h +irc-modelist.c irc-modelist.h irc-msgbuffer.c irc-msgbuffer.h irc-nick.c irc-nick.h irc-notify.c irc-notify.h diff --git a/src/plugins/irc/Makefile.am b/src/plugins/irc/Makefile.am index 208ce118f..966dc6813 100644 --- a/src/plugins/irc/Makefile.am +++ b/src/plugins/irc/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> +# Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> # # This file is part of WeeChat, the extensible chat client. # @@ -53,6 +53,8 @@ irc_la_SOURCES = irc.c \ irc-message.h \ irc-mode.c \ irc-mode.h \ + irc-modelist.c \ + irc-modelist.h \ irc-msgbuffer.c \ irc-msgbuffer.h \ irc-nick.c \ diff --git a/src/plugins/irc/irc-bar-item.c b/src/plugins/irc/irc-bar-item.c index e4494bb0b..02428b9a8 100644 --- a/src/plugins/irc/irc-bar-item.c +++ b/src/plugins/irc/irc-bar-item.c @@ -1,7 +1,7 @@ /* * irc-bar-item.c - bar items for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -280,7 +280,7 @@ irc_bar_item_buffer_modes (const void *pointer, void *data, modes_without_args = NULL; if (!irc_config_display_channel_modes_arguments (channel->modes)) { - pos_space = strchr(channel->modes, ' '); + pos_space = strchr (channel->modes, ' '); if (pos_space) { modes_without_args = weechat_strndup ( diff --git a/src/plugins/irc/irc-bar-item.h b/src/plugins/irc/irc-bar-item.h index 5889ea599..1173f9e72 100644 --- a/src/plugins/irc/irc-bar-item.h +++ b/src/plugins/irc/irc-bar-item.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,10 +17,10 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_BAR_ITEM_H -#define WEECHAT_IRC_BAR_ITEM_H 1 +#ifndef WEECHAT_PLUGIN_IRC_BAR_ITEM_H +#define WEECHAT_PLUGIN_IRC_BAR_ITEM_H extern void irc_bar_item_update_channel (); extern void irc_bar_item_init (); -#endif /* WEECHAT_IRC_BAR_ITEM_H */ +#endif /* WEECHAT_PLUGIN_IRC_BAR_ITEM_H */ diff --git a/src/plugins/irc/irc-buffer.c b/src/plugins/irc/irc-buffer.c index b0a1e5ccd..7928c65ee 100644 --- a/src/plugins/irc/irc-buffer.c +++ b/src/plugins/irc/irc-buffer.c @@ -1,7 +1,7 @@ /* * irc-buffer.c - buffer functions for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-buffer.h b/src/plugins/irc/irc-buffer.h index cd0d828ce..034398e40 100644 --- a/src/plugins/irc/irc-buffer.h +++ b/src/plugins/irc/irc-buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_BUFFER_H -#define WEECHAT_IRC_BUFFER_H 1 +#ifndef WEECHAT_PLUGIN_IRC_BUFFER_H +#define WEECHAT_PLUGIN_IRC_BUFFER_H #define IRC_BUFFER_GET_SERVER(__buffer) \ struct t_weechat_plugin *buffer_plugin = NULL; \ @@ -56,4 +56,4 @@ extern int irc_buffer_nickcmp_cb (const void *pointer, void *data, extern struct t_gui_buffer *irc_buffer_search_server_lowest_number (); extern struct t_gui_buffer *irc_buffer_search_private_lowest_number (struct t_irc_server *server); -#endif /* WEECHAT_IRC_BUFFER_H */ +#endif /* WEECHAT_PLUGIN_IRC_BUFFER_H */ diff --git a/src/plugins/irc/irc-channel.c b/src/plugins/irc/irc-channel.c index b184a5330..ab24038a0 100644 --- a/src/plugins/irc/irc-channel.c +++ b/src/plugins/irc/irc-channel.c @@ -1,7 +1,7 @@ /* * irc-channel.c - channel and private chat management for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -33,6 +33,7 @@ #include "irc-color.h" #include "irc-command.h" #include "irc-config.h" +#include "irc-modelist.h" #include "irc-nick.h" #include "irc-server.h" #include "irc-input.h" @@ -356,7 +357,7 @@ irc_channel_create_buffer (struct t_irc_server *server, } /* set highlights settings on channel buffer */ - weechat_buffer_set( + weechat_buffer_set ( ptr_buffer, "highlight_words_add", (channel_type == IRC_CHANNEL_TYPE_CHANNEL) ? @@ -426,6 +427,7 @@ irc_channel_new (struct t_irc_server *server, int channel_type, { struct t_irc_channel *new_channel; struct t_gui_buffer *ptr_buffer; + const char *ptr_chanmode; /* create buffer for channel (or use existing one) */ ptr_buffer = irc_channel_create_buffer (server, channel_type, @@ -479,6 +481,14 @@ irc_channel_new (struct t_irc_server *server, int channel_type, new_channel->nicks_speaking[1] = NULL; new_channel->nicks_speaking_time = NULL; new_channel->last_nick_speaking_time = NULL; + new_channel->modelists = NULL; + new_channel->last_modelist = NULL; + for (ptr_chanmode = irc_server_get_chanmodes (server); ptr_chanmode[0]; + ptr_chanmode++) + { + if (ptr_chanmode[0] != ',') + irc_modelist_new (new_channel, ptr_chanmode[0]); + } new_channel->join_smart_filtered = NULL; new_channel->buffer = ptr_buffer; new_channel->buffer_as_string = NULL; @@ -711,8 +721,8 @@ irc_channel_check_whox (struct t_irc_server *server, } else { - irc_channel_remove_account(server, channel); - irc_channel_remove_away(server, channel); + irc_channel_remove_account (server, channel); + irc_channel_remove_away (server, channel); } } } @@ -1360,6 +1370,22 @@ irc_channel_display_nick_back_in_pv (struct t_irc_server *server, } /* + * Sets state for modelists in a channel. + */ + +void +irc_channel_modelist_set_state (struct t_irc_channel *channel, int state) +{ + struct t_irc_modelist *ptr_modelist; + + for (ptr_modelist = channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + ptr_modelist->state = state; + } +} + +/* * Frees a channel and remove it from channels list. */ @@ -1387,6 +1413,7 @@ irc_channel_free (struct t_irc_server *server, struct t_irc_channel *channel) /* free linked lists */ irc_nick_free_all (server, channel); + irc_modelist_free_all (channel); /* free channel data */ if (channel->name) @@ -1472,6 +1499,8 @@ irc_channel_hdata_channel_cb (const void *pointer, void *data, WEECHAT_HDATA_VAR(struct t_irc_channel, nicks_speaking, POINTER, 0, NULL, NULL); WEECHAT_HDATA_VAR(struct t_irc_channel, nicks_speaking_time, POINTER, 0, NULL, "irc_channel_speaking"); WEECHAT_HDATA_VAR(struct t_irc_channel, last_nick_speaking_time, POINTER, 0, NULL, "irc_channel_speaking"); + WEECHAT_HDATA_VAR(struct t_irc_channel, modelists, POINTER, 0, NULL, "irc_modelist"); + WEECHAT_HDATA_VAR(struct t_irc_channel, last_modelist, POINTER, 0, NULL, "irc_modelist"); WEECHAT_HDATA_VAR(struct t_irc_channel, join_smart_filtered, HASHTABLE, 0, NULL, NULL); WEECHAT_HDATA_VAR(struct t_irc_channel, buffer, POINTER, 0, NULL, "buffer"); WEECHAT_HDATA_VAR(struct t_irc_channel, buffer_as_string, STRING, 0, NULL, NULL); @@ -1629,6 +1658,7 @@ irc_channel_print_log (struct t_irc_channel *channel) struct t_irc_channel_speaking *ptr_nick_speaking; int i, index; struct t_irc_nick *ptr_nick; + struct t_irc_modelist *ptr_modelist; weechat_log_printf (""); weechat_log_printf (" => channel %s (addr:0x%lx):", channel->name, channel); @@ -1656,6 +1686,8 @@ irc_channel_print_log (struct t_irc_channel *channel) weechat_log_printf (" nicks_speaking[1]. . . . : 0x%lx", channel->nicks_speaking[1]); weechat_log_printf (" nicks_speaking_time. . . : 0x%lx", channel->nicks_speaking_time); weechat_log_printf (" last_nick_speaking_time. : 0x%lx", channel->last_nick_speaking_time); + weechat_log_printf (" modelists. . . . . . . . : 0x%lx", channel->modelists); + weechat_log_printf (" last_modelist. . . . . . : 0x%lx", channel->last_modelist); weechat_log_printf (" join_smart_filtered. . . : 0x%lx (hashtable: '%s')", channel->join_smart_filtered, weechat_hashtable_get_string (channel->join_smart_filtered, @@ -1686,13 +1718,18 @@ irc_channel_print_log (struct t_irc_channel *channel) ptr_nick_speaking; ptr_nick_speaking = ptr_nick_speaking->next_nick) { - weechat_log_printf (" nick speaking time: '%s', time: %ld", + weechat_log_printf (" nick speaking time: '%s', time: %lld", ptr_nick_speaking->nick, - ptr_nick_speaking->time_last_message); + (long long)ptr_nick_speaking->time_last_message); } } for (ptr_nick = channel->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick) { irc_nick_print_log (ptr_nick); } + for (ptr_modelist = channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + irc_modelist_print_log (ptr_modelist); + } } diff --git a/src/plugins/irc/irc-channel.h b/src/plugins/irc/irc-channel.h index 73a68b712..d078d1d33 100644 --- a/src/plugins/irc/irc-channel.h +++ b/src/plugins/irc/irc-channel.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_CHANNEL_H -#define WEECHAT_IRC_CHANNEL_H 1 +#ifndef WEECHAT_PLUGIN_IRC_CHANNEL_H +#define WEECHAT_PLUGIN_IRC_CHANNEL_H #include <time.h> @@ -32,6 +32,7 @@ #define IRC_CHANNEL_NICKS_SPEAKING_LIMIT 128 struct t_irc_server; +struct t_irc_modelist; struct t_irc_channel_speaking { @@ -71,6 +72,8 @@ struct t_irc_channel struct t_irc_channel_speaking *nicks_speaking_time; /* for smart filter */ /* of join/part/quit messages */ struct t_irc_channel_speaking *last_nick_speaking_time; + struct t_irc_modelist *modelists; /* modelists in the channel */ + struct t_irc_modelist *last_modelist; /* last modelist in the channel */ struct t_hashtable *join_smart_filtered; /* smart filtered joins */ struct t_gui_buffer *buffer; /* buffer allocated for channel */ char *buffer_as_string; /* used to return buffer info */ @@ -158,6 +161,8 @@ extern int irc_channel_autorejoin_cb (const void *pointer, void *data, extern void irc_channel_display_nick_back_in_pv (struct t_irc_server *server, struct t_irc_nick *nick, const char *nickname); +extern void irc_channel_modelist_set_state (struct t_irc_channel *channel, + int state); extern struct t_hdata *irc_channel_hdata_channel_cb (const void *pointer, void *data, const char *hdata_name); @@ -168,4 +173,4 @@ extern int irc_channel_add_to_infolist (struct t_infolist *infolist, struct t_irc_channel *channel); extern void irc_channel_print_log (struct t_irc_channel *channel); -#endif /* WEECHAT_IRC_CHANNEL_H */ +#endif /* WEECHAT_PLUGIN_IRC_CHANNEL_H */ diff --git a/src/plugins/irc/irc-color.c b/src/plugins/irc/irc-color.c index 20395c385..2f33e7db3 100644 --- a/src/plugins/irc/irc-color.c +++ b/src/plugins/irc/irc-color.c @@ -1,7 +1,7 @@ /* * irc-color.c - IRC color decoding/encoding in messages * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-color.h b/src/plugins/irc/irc-color.h index 218c20432..82004cff5 100644 --- a/src/plugins/irc/irc-color.h +++ b/src/plugins/irc/irc-color.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_COLOR_H -#define WEECHAT_IRC_COLOR_H 1 +#ifndef WEECHAT_PLUGIN_IRC_COLOR_H +#define WEECHAT_PLUGIN_IRC_COLOR_H #define IRC_NUM_COLORS 100 @@ -114,4 +114,4 @@ extern char *irc_color_for_tags (const char *color); extern int irc_color_weechat_add_to_infolist (struct t_infolist *infolist); extern void irc_color_end (); -#endif /* WEECHAT_IRC_COLOR_H */ +#endif /* WEECHAT_PLUGIN_IRC_COLOR_H */ diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c index bb40e000d..22a1977e2 100644 --- a/src/plugins/irc/irc-command.c +++ b/src/plugins/irc/irc-command.c @@ -1,7 +1,7 @@ /* * irc-command.c - IRC commands * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -30,6 +30,7 @@ #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> +#include <regex.h> #include "../weechat-plugin.h" #include "irc.h" @@ -42,6 +43,7 @@ #include "irc-input.h" #include "irc-message.h" #include "irc-mode.h" +#include "irc-modelist.h" #include "irc-msgbuffer.h" #include "irc-nick.h" #include "irc-notify.h" @@ -238,6 +240,10 @@ irc_command_mode_masks (struct t_irc_server *server, char modes[128+1], masks[1024], *mask; struct t_irc_channel *ptr_channel; struct t_irc_nick *ptr_nick; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; + long number; + char *error; if (irc_mode_get_chanmode_type (server, mode[0]) != 'A') { @@ -265,15 +271,31 @@ irc_command_mode_masks (struct t_irc_server *server, masks[0] = '\0'; ptr_channel = irc_channel_search (server, channel_name); + ptr_modelist = irc_modelist_search (ptr_channel, mode[0]); for (; argv[pos_masks]; pos_masks++) { mask = NULL; - /* use default_ban_mask for nick arguments */ if (ptr_channel) { - if (!strchr (argv[pos_masks], '!') + /* use modelist item for number arguments */ + if (ptr_modelist && (set[0] == '-')) + { + error = NULL; + number = strtol (argv[pos_masks], &error, 10); + if (error && !error[0]) + { + ptr_item = irc_modelist_item_search_number (ptr_modelist, + number - 1); + if (ptr_item) + mask = strdup (ptr_item->mask); + } + } + + /* use default_ban_mask for nick arguments */ + if (!mask + && !strchr (argv[pos_masks], '!') && !strchr (argv[pos_masks], '@')) { ptr_nick = irc_nick_search (server, ptr_channel, @@ -1544,8 +1566,8 @@ IRC_COMMAND_CALLBACK(ctcp) { /* generate argument for PING if not provided */ gettimeofday (&tv, NULL); - snprintf (str_time, sizeof (str_time), "%ld %ld", - (long)tv.tv_sec, (long)tv.tv_usec); + snprintf (str_time, sizeof (str_time), "%lld %ld", + (long long)tv.tv_sec, (long)tv.tv_usec); ctcp_args = str_time; } else @@ -2562,7 +2584,8 @@ irc_command_join_server (struct t_irc_server *server, const char *arguments, } } if (manual_join - && weechat_config_boolean (irc_config_look_buffer_open_before_join)) + && weechat_config_boolean (irc_config_look_buffer_open_before_join) + && !irc_channel_search (server, pos_channel)) { /* * open the channel buffer immediately (do not wait for the @@ -2914,98 +2937,95 @@ IRC_COMMAND_CALLBACK(links) IRC_COMMAND_CALLBACK(list) { char buf[512], *ptr_channel_name, *ptr_server_name, *ptr_regex; + regex_t *new_regexp; int i, ret; IRC_BUFFER_GET_SERVER(buffer); - IRC_COMMAND_CHECK_SERVER("list", 1); /* make C compiler happy */ (void) pointer; (void) data; - if (ptr_server->cmd_list_regexp) + ptr_channel_name = NULL; + ptr_server_name = NULL; + ptr_regex = NULL; + new_regexp = NULL; + + for (i = 1; i < argc; i++) { - regfree (ptr_server->cmd_list_regexp); - free (ptr_server->cmd_list_regexp); - ptr_server->cmd_list_regexp = NULL; + if (weechat_strcasecmp (argv[i], "-server") == 0) + { + if (argc <= i + 1) + WEECHAT_COMMAND_ERROR; + ptr_server = irc_server_search (argv[i + 1]); + if (!ptr_server) + WEECHAT_COMMAND_ERROR; + i++; + } + else if (weechat_strcasecmp (argv[i], "-re") == 0) + { + if (argc <= i + 1) + WEECHAT_COMMAND_ERROR; + ptr_regex = argv_eol[i + 1]; + i++; + } + else if (!ptr_channel_name) + ptr_channel_name = argv[i]; + else if (!ptr_server_name) + ptr_server_name = argv[i]; + else + WEECHAT_COMMAND_ERROR; } - if (argc > 1) + IRC_COMMAND_CHECK_SERVER("list", 1); + + if (ptr_regex) { - ptr_channel_name = NULL; - ptr_server_name = NULL; - ptr_regex = NULL; - for (i = 1; i < argc; i++) + new_regexp = malloc (sizeof (*new_regexp)); + if (!new_regexp) { - if (weechat_strcasecmp (argv[i], "-re") == 0) - { - if (i < argc - 1) - { - ptr_regex = argv_eol[i + 1]; - i++; - } - } - else - { - if (!ptr_channel_name) - ptr_channel_name = argv[i]; - else if (!ptr_server_name) - ptr_server_name = argv[i]; - } + weechat_printf ( + ptr_server->buffer, + _("%s%s: not enough memory for regular expression"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + return WEECHAT_RC_OK; } - if (!ptr_channel_name && !ptr_server_name && !ptr_regex) + ret = weechat_string_regcomp (new_regexp, + ptr_regex, + REG_EXTENDED | REG_ICASE | REG_NOSUB); + if (ret != 0) { - irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL, - "LIST"); + regerror (ret, new_regexp, buf, sizeof (buf)); + weechat_printf ( + ptr_server->buffer, + _("%s%s: \"%s\" is not a valid regular expression " + "(%s)"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, + ptr_regex, buf); + free (new_regexp); + return WEECHAT_RC_OK; } - else + if (ptr_server->cmd_list_regexp) { - if (ptr_regex) - { - ptr_server->cmd_list_regexp = malloc ( - sizeof (*ptr_server->cmd_list_regexp)); - if (ptr_server->cmd_list_regexp) - { - if ((ret = weechat_string_regcomp ( - ptr_server->cmd_list_regexp, ptr_regex, - REG_EXTENDED | REG_ICASE | REG_NOSUB)) != 0) - { - regerror (ret, ptr_server->cmd_list_regexp, - buf, sizeof(buf)); - weechat_printf ( - ptr_server->buffer, - _("%s%s: \"%s\" is not a valid regular expression " - "(%s)"), - weechat_prefix ("error"), IRC_PLUGIN_NAME, - argv_eol[1], buf); - free (ptr_server->cmd_list_regexp); - ptr_server->cmd_list_regexp = NULL; - return WEECHAT_RC_OK; - } - } - else - { - weechat_printf ( - ptr_server->buffer, - _("%s%s: not enough memory for regular expression"), - weechat_prefix ("error"), IRC_PLUGIN_NAME); - return WEECHAT_RC_OK; - } - } - irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL, - "LIST%s%s%s%s", - (ptr_channel_name) ? " " : "", - (ptr_channel_name) ? ptr_channel_name : "", - (ptr_server_name) ? " " : "", - (ptr_server_name) ? ptr_server_name : ""); + regfree (ptr_server->cmd_list_regexp); + free (ptr_server->cmd_list_regexp); } + ptr_server->cmd_list_regexp = new_regexp; } - else + else if (ptr_server->cmd_list_regexp) { - irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL, - "LIST"); + regfree (ptr_server->cmd_list_regexp); + free (ptr_server->cmd_list_regexp); + ptr_server->cmd_list_regexp = NULL; } + irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL, + "LIST%s%s%s%s", + (ptr_channel_name) ? " " : "", + (ptr_channel_name) ? ptr_channel_name : "", + (ptr_server_name) ? " " : "", + (ptr_server_name) ? ptr_server_name : ""); + return WEECHAT_RC_OK; } @@ -4606,13 +4626,22 @@ IRC_COMMAND_CALLBACK(saquit) void irc_command_display_server (struct t_irc_server *server, int with_detail) { - char *cmd_pwd_hidden; + char *cmd_pwd_hidden, str_nick[1024]; int num_channels, num_pv; + str_nick[0] = '\0'; + if (server->nick) + { + snprintf (str_nick, sizeof (str_nick), + ", %s %s", + _("nick:"), + server->nick); + } + if (with_detail) { weechat_printf (NULL, ""); - weechat_printf (NULL, _("Server: %s%s %s[%s%s%s]%s%s"), + weechat_printf (NULL, _("Server: %s%s %s[%s%s%s]%s%s%s"), IRC_COLOR_CHAT_SERVER, server->name, IRC_COLOR_CHAT_DELIMITERS, @@ -4621,6 +4650,7 @@ irc_command_display_server (struct t_irc_server *server, int with_detail) _("connected") : _("not connected"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_RESET, + str_nick, (server->temp_server) ? _(" (temporary)") : ""); /* addresses */ if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_ADDRESSES])) @@ -4986,6 +5016,15 @@ irc_command_display_server (struct t_irc_server *server, int with_detail) weechat_printf (NULL, " notify . . . . . . . : %s'%s'", IRC_COLOR_CHAT_VALUE, weechat_config_string (server->options[IRC_SERVER_OPTION_NOTIFY])); + + /* split_msg_max_length */ + if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH])) + weechat_printf (NULL, " split_msg_max_length : (%d)", + IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH)); + else + weechat_printf (NULL, " split_msg_max_length : %s%d", + IRC_COLOR_CHAT_VALUE, + weechat_config_integer (server->options[IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH])); } else { @@ -4995,16 +5034,16 @@ irc_command_display_server (struct t_irc_server *server, int with_detail) num_pv = irc_server_get_pv_count (server); weechat_printf ( NULL, - " %s %s%s %s[%s%s%s]%s%s, %d %s, %d pv", + " %s %s%s %s[%s%s%s]%s%s%s, %d %s, %d pv", (server->is_connected) ? "*" : " ", IRC_COLOR_CHAT_SERVER, server->name, IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_RESET, - (server->is_connected) ? - _("connected") : _("not connected"), + (server->is_connected) ? _("connected") : _("not connected"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_RESET, + str_nick, (server->temp_server) ? _(" (temporary)") : "", num_channels, NG_("channel", "channels", num_channels), @@ -6563,20 +6602,21 @@ irc_command_init () "links", N_("list all servernames which are known by the server answering the " "query"), - N_("[[<server>] <server_mask>]"), - N_(" server: this server should answer the query\n" + N_("[[<target>] <server_mask>]"), + N_(" target: this remote server should answer the query\n" "server_mask: list of servers must match this mask"), NULL, &irc_command_links, NULL, NULL); weechat_hook_command ( "list", N_("list channels and their topic"), - N_("[<channel>[,<channel>...]] [<server>] " - "[-re <regex>]"), - N_("channel: channel to list\n" - " server: server name\n" + N_("[-server <server>] [-re <regex>] [<channel>[,<channel>...]] " + "[<target>]"), + N_(" server: send to this server (internal name)\n" " regex: POSIX extended regular expression used to filter results " "(case insensitive, can start by \"(?-i)\" to become case " "sensitive)\n" + "channel: channel to list\n" + " target: server name\n" "\n" "Examples:\n" " list all channels on server (can be very slow on large networks):\n" @@ -6586,7 +6626,9 @@ irc_command_init () " list all channels beginning with \"#weechat\" (can be very slow " "on large networks):\n" " /list -re #weechat.*"), - NULL, &irc_command_list, NULL, NULL); + "-server %(irc_servers)" + " || -re", + &irc_command_list, NULL, NULL); weechat_hook_command ( "lusers", N_("get statistics about the size of the IRC network"), @@ -6732,9 +6774,9 @@ irc_command_init () weechat_hook_command ( "ping", N_("send a ping to server"), - N_("<server1> [<server2>]"), - N_("server1: server\n" - "server2: forward ping to this server"), + N_("<target1> [<target2>]"), + N_("target1: server\n" + "target2: forward ping to this server"), NULL, &irc_command_ping, NULL, NULL); weechat_hook_command ( "pong", @@ -6849,18 +6891,20 @@ irc_command_init () weechat_hook_command ( "server", N_("list, add or remove IRC servers"), - N_("list|listfull [<server>]" - " || add <server> <hostname>[/<port>] [-temp] [-<option>[=<value>]] " + N_("list|listfull [<name>]" + " || add <name> <hostname>[/<port>] [-temp] [-<option>[=<value>]] " "[-no<option>]" - " || copy|rename <server> <new_name>" - " || reorder <server> [<server>...]" - " || open <server>|-all [<server>...]" - " || del|keep <server>" + " || copy|rename <name> <new_name>" + " || reorder <name> [<name>...]" + " || open <name>|-all [<name>...]" + " || del|keep <name>" " || deloutq|jump|raw"), N_(" list: list servers (without argument, this list is displayed)\n" "listfull: list servers with detailed info for each server\n" " add: add a new server\n" - " server: server name, for internal and display use\n" + " name: server name, for internal and display use; this name " + "is used to connect to the server (/connect name) and to set server " + "options: irc.server.name.xxx\n" "hostname: name or IP address of server, with optional port " "(default: 6667), many addresses can be separated by a comma\n" " -temp: add a temporary server (not saved)\n" @@ -6919,16 +6963,16 @@ irc_command_init () weechat_hook_command ( "squit", N_("disconnect server links"), - N_("<server> <comment>"), - N_( " server: server name\n" + N_("<target> <comment>"), + N_( " target: server name\n" "comment: comment"), NULL, &irc_command_squit, NULL, NULL); weechat_hook_command ( "stats", N_("query statistics about server"), - N_("[<query> [<server>]]"), + N_("[<query> [<target>]]"), N_(" query: c/h/i/k/l/m/o/y/u (see RFC1459)\n" - "server: server name"), + "target: server name"), NULL, &irc_command_stats, NULL, NULL); weechat_hook_command ( "summon", @@ -6963,17 +7007,21 @@ irc_command_init () weechat_hook_command ( "unban", N_("unban nicks or hosts"), - N_("[<channel>] <nick> [<nick>...]"), + N_("[<channel>] <nick>|<number> [<nick>|<number>...]"), N_("channel: channel name\n" - " nick: nick or host"), - NULL, &irc_command_unban, NULL, NULL); + " nick: nick or host\n" + " number: ban number (as displayed by command /ban)"), + "%(irc_modelist_masks:b)|%(irc_modelist_numbers:b)", + &irc_command_unban, NULL, NULL); weechat_hook_command ( "unquiet", N_("unquiet nicks or hosts"), - N_("[<channel>] <nick> [<nick>...]"), + N_("[<channel>] <nick>|<number> [<nick>|<number>...]"), N_("channel: channel name\n" - " nick: nick or host"), - "%(irc_channel_nicks_hosts)", &irc_command_unquiet, NULL, NULL); + " nick: nick or host\n" + " number: quiet number (as displayed by command /quiet)"), + "%(irc_modelist_masks:q)|%(irc_modelist_numbers:q)", + &irc_command_unquiet, NULL, NULL); weechat_hook_command ( "userhost", N_("return a list of information about nicks"), @@ -6989,8 +7037,8 @@ irc_command_init () weechat_hook_command ( "version", N_("give the version info of nick or server (current or specified)"), - N_("[<server>|<nick>]"), - N_("server: server name\n" + N_("[<target>|<nick>]"), + N_("target: server name\n" " nick: nick"), "%(nicks)", &irc_command_version, NULL, NULL); weechat_hook_command ( @@ -7024,8 +7072,8 @@ irc_command_init () weechat_hook_command ( "whois", N_("query information about user(s)"), - N_("[<server>] [<nick>[,<nick>...]]"), - N_("server: server name\n" + N_("[<target>] [<nick>[,<nick>...]]"), + N_("target: server name\n" " nick: nick (may be a mask)\n" "\n" "Without argument, this command will do a whois on:\n" diff --git a/src/plugins/irc/irc-command.h b/src/plugins/irc/irc-command.h index 67ddd506e..c6a31dc57 100644 --- a/src/plugins/irc/irc-command.h +++ b/src/plugins/irc/irc-command.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_COMMAND_H -#define WEECHAT_IRC_COMMAND_H 1 +#ifndef WEECHAT_PLUGIN_IRC_COMMAND_H +#define WEECHAT_PLUGIN_IRC_COMMAND_H struct t_irc_server; struct t_irc_channel; @@ -77,4 +77,4 @@ extern void irc_command_quit_server (struct t_irc_server *server, const char *arguments); extern void irc_command_init (); -#endif /* WEECHAT_IRC_COMMAND_H */ +#endif /* WEECHAT_PLUGIN_IRC_COMMAND_H */ diff --git a/src/plugins/irc/irc-completion.c b/src/plugins/irc/irc-completion.c index 3562e3d84..4e72a8570 100644 --- a/src/plugins/irc/irc-completion.c +++ b/src/plugins/irc/irc-completion.c @@ -1,7 +1,7 @@ /* * irc-completion.c - completion for IRC commands * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -31,6 +31,7 @@ #include "irc-completion.h" #include "irc-config.h" #include "irc-ignore.h" +#include "irc-modelist.h" #include "irc-nick.h" #include "irc-notify.h" #include "irc-server.h" @@ -421,6 +422,92 @@ irc_completion_channel_nicks_hosts_cb (const void *pointer, void *data, } /* + * Adds modelist masks of current channel to completion list. + */ + +int +irc_completion_modelist_masks_cb (const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + char *pos; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; + + IRC_BUFFER_GET_SERVER_CHANNEL(buffer); + + /* make C compiler happy */ + (void) pointer; + (void) data; + + pos = strchr (completion_item, ':'); + if (pos) + pos++; + + if (pos && pos[0] && ptr_channel) + { + ptr_modelist = irc_modelist_search (ptr_channel, pos[0]); + if (ptr_modelist) + { + for (ptr_item = ptr_modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + weechat_hook_completion_list_add (completion, + ptr_item->mask, + 0, WEECHAT_LIST_POS_END); + } + } + } + + return WEECHAT_RC_OK; +} + +/* + * Adds modelist numbers of current channel to completion list. + */ + +int +irc_completion_modelist_numbers_cb (const void *pointer, void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + char *pos, str_number[32]; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; + + IRC_BUFFER_GET_SERVER_CHANNEL(buffer); + + /* make C compiler happy */ + (void) pointer; + (void) data; + + pos = strchr (completion_item, ':'); + if (pos) + pos++; + + if (pos && pos[0] && ptr_channel) + { + ptr_modelist = irc_modelist_search (ptr_channel, pos[0]); + if (ptr_modelist) + { + for (ptr_item = ptr_modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + snprintf (str_number, sizeof (str_number), + "%d", ptr_item->number + 1); + weechat_hook_completion_list_add (completion, + str_number, + 0, WEECHAT_LIST_POS_END); + } + } + } + + return WEECHAT_RC_OK; +} + +/* * Adds topic of current channel to completion list. */ @@ -758,6 +845,14 @@ irc_completion_init () weechat_hook_completion ("irc_channel_nicks_hosts", N_("nicks and hostnames of current IRC channel"), &irc_completion_channel_nicks_hosts_cb, NULL, NULL); + weechat_hook_completion ("irc_modelist_masks", + N_("modelist masks of current IRC channel; " + "required argument: modelist mode"), + &irc_completion_modelist_masks_cb, NULL, NULL); + weechat_hook_completion ("irc_modelist_numbers", + N_("modelist numbers of current IRC channel; " + "required argument: modelist mode"), + &irc_completion_modelist_numbers_cb, NULL, NULL); weechat_hook_completion ("irc_channel_topic", N_("topic of current IRC channel"), &irc_completion_channel_topic_cb, NULL, NULL); diff --git a/src/plugins/irc/irc-completion.h b/src/plugins/irc/irc-completion.h index 5d644f44c..21659d1a5 100644 --- a/src/plugins/irc/irc-completion.h +++ b/src/plugins/irc/irc-completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_COMPLETION_H -#define WEECHAT_IRC_COMPLETION_H 1 +#ifndef WEECHAT_PLUGIN_IRC_COMPLETION_H +#define WEECHAT_PLUGIN_IRC_COMPLETION_H extern void irc_completion_init (); -#endif /* WEECHAT_IRC_COMPLETION_H */ +#endif /* WEECHAT_PLUGIN_IRC_COMPLETION_H */ diff --git a/src/plugins/irc/irc-config.c b/src/plugins/irc/irc-config.c index 1b1c85a98..04bccb25c 100644 --- a/src/plugins/irc/irc-config.c +++ b/src/plugins/irc/irc-config.c @@ -1,7 +1,7 @@ /* * irc-config.c - IRC configuration options (file irc.conf) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -23,7 +23,6 @@ #include <unistd.h> #include <stdio.h> #include <string.h> -#include <ctype.h> #include <time.h> #include <limits.h> #include <pwd.h> @@ -224,7 +223,7 @@ irc_config_compute_nick_colors () } /* if colors are displayed for nicks in nicklist, refresh them */ - if (weechat_config_boolean(irc_config_look_color_nicks_in_nicklist)) + if (weechat_config_boolean (irc_config_look_color_nicks_in_nicklist)) irc_nick_nicklist_set_color_all (); } @@ -995,11 +994,9 @@ irc_config_server_check_value_cb (const void *pointer, void *data, { int index_option, proxy_found; const char *pos_error, *proxy_name; + char *error; + long number; struct t_infolist *infolist; -#ifdef HAVE_GNUTLS - char *fingerprint_eval, **fingerprints, *str_sizes; - int i, j, rc, algo, length; -#endif /* HAVE_GNUTLS */ /* make C compiler happy */ (void) data; @@ -1051,81 +1048,30 @@ irc_config_server_check_value_cb (const void *pointer, void *data, return 0; } break; - case IRC_SERVER_OPTION_SSL_FINGERPRINT: -#ifdef HAVE_GNUTLS + case IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH: if (!value || !value[0]) break; - fingerprint_eval = weechat_string_eval_expression ( - value, NULL, NULL, NULL); - if (!fingerprint_eval || !fingerprint_eval[0]) - { - weechat_printf ( - NULL, - _("%s%s: the evaluated fingerprint must not be " - "empty"), - weechat_prefix ("error"), - IRC_PLUGIN_NAME); - if (fingerprint_eval) - free (fingerprint_eval); - return 0; - } - fingerprints = weechat_string_split ( - (fingerprint_eval) ? fingerprint_eval : value, - ",", 0, 0, NULL); - if (!fingerprints) + error = NULL; + number = strtol (value, &error, 10); + if (!error || error[0]) { - free (fingerprint_eval); + /* + * not a valid number, but we return 1 (OK) to let WeeChat + * display the appropriate error + */ return 1; } - rc = 0; - for (i = 0; fingerprints[i]; i++) - { - length = strlen (fingerprints[i]); - algo = irc_server_fingerprint_search_algo_with_size ( - length * 4); - if (algo < 0) - { - rc = -1; - break; - } - for (j = 0; j < length; j++) - { - if (!isxdigit ((unsigned char)fingerprints[i][j])) - { - rc = -2; - break; - } - } - if (rc < 0) - break; - } - weechat_string_free_split (fingerprints); - free (fingerprint_eval); - switch (rc) + if ((number < 0) + || ((number > 0) && (number < 128)) + || (number > 4096)) { - case -1: /* invalid size */ - str_sizes = irc_server_fingerprint_str_sizes (); - weechat_printf ( - NULL, - _("%s%s: invalid fingerprint size, the " - "number of hexadecimal digits must be " - "one of: %s"), - weechat_prefix ("error"), - IRC_PLUGIN_NAME, - (str_sizes) ? str_sizes : "?"); - if (str_sizes) - free (str_sizes); - return 0; - case -2: /* invalid content */ - weechat_printf ( + weechat_printf ( NULL, - _("%s%s: invalid fingerprint, it must " - "contain only hexadecimal digits (0-9, " - "a-f)"), + _("%s%s: invalid length for split, it must be " + "either 0 or any integer between 128 and 4096"), weechat_prefix ("error"), IRC_PLUGIN_NAME); - return 0; + return 0; } -#endif /* HAVE_GNUTLS */ break; } } @@ -1533,7 +1479,9 @@ irc_config_server_new_option (struct t_config_file *config_file, option_name, "string", N_("list of hostname/port or IP/port for server (separated by " "comma) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1660,7 +1608,9 @@ irc_config_server_new_option (struct t_config_file *config_file, "fingerprints can be separated by commas; if this option " "is set, the other checks on certificates are NOT " "performed (option \"ssl_verify\") " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1693,7 +1643,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("password for server " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1757,7 +1709,9 @@ irc_config_server_new_option (struct t_config_file *config_file, option_name, "string", N_("username for SASL authentication; this option is not used " "for mechanism \"external\" " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1776,7 +1730,9 @@ irc_config_server_new_option (struct t_config_file *config_file, N_("password for SASL authentication; this option is not used " "for mechanisms \"ecdsa-nist256p-challenge\" and " "\"external\" " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1898,7 +1854,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("nicknames to use on server (separated by comma) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1935,7 +1893,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("user name to use on server " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1952,7 +1912,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("real name to use on server " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1989,7 +1951,10 @@ irc_config_server_new_option (struct t_config_file *config_file, "executing command and the auto-join of channels; examples: " "\"+R\" (to set mode \"R\"), \"+R-i\" (to set mode \"R\" " "and remove \"i\"); see /help mode for the complete mode " - "syntax (note: content is evaluated, see /help eval)"), + "syntax " + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -2009,7 +1974,9 @@ irc_config_server_new_option (struct t_config_file *config_file, "auto-join of channels (many commands can be separated by " "\";\", use \"\\;\" for a semicolon, special variables " "$nick, $channel and $server are replaced by their value) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -2050,7 +2017,9 @@ irc_config_server_new_option (struct t_config_file *config_file, "channels (separated by a space) (example: \"#channel1," "#channel2,#channel3 key1,key2\" where #channel1 and " "#channel2 are protected by key1 and key2) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -2264,6 +2233,29 @@ irc_config_server_new_option (struct t_config_file *config_file, callback_change_data, NULL, NULL, NULL); break; + case IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH: + new_option = weechat_config_new_option ( + config_file, section, + option_name, "integer", + N_("split outgoing IRC messages to fit in this number of chars; " + "the default value is 512, this is a safe and recommended " + "value; " + "value 0 disables the split (not recommended, unless you " + "know what you do); allowed values are 0 or " + "any integer between 128 and 4096; " + "this option should be changed only on non-standard IRC " + "servers, for example gateways like bitlbee"), + NULL, 0, 4096, + default_value, value, + null_value_allowed, + callback_check_value, + callback_check_value_pointer, + callback_check_value_data, + callback_change, + callback_change_pointer, + callback_change_data, + NULL, NULL, NULL); + break; case IRC_SERVER_NUM_OPTIONS: break; } @@ -2510,6 +2502,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } @@ -2816,9 +2809,10 @@ irc_config_init () irc_config_file, ptr_section, "notice_welcome_redirect", "boolean", N_("automatically redirect channel welcome notices to the channel " - "buffer; such notices have the nick as target but a channel name in " - "beginning of notice message, for example notices sent by freenode " - "server which look like: \"[#channel] Welcome to this channel...\""), + "buffer; such notices have the nick as target but a channel name " + "in beginning of notice message, for example the ENTRYMSG notices " + "sent by Atheme IRC Services which look like: " + "\"[#channel] Welcome to this channel...\""), NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); irc_config_look_notice_welcome_tags = weechat_config_new_option ( @@ -2968,6 +2962,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } @@ -3097,6 +3092,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } @@ -3242,6 +3238,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } irc_config_section_msgbuffer = ptr_section; @@ -3258,6 +3255,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } irc_config_section_ctcp = ptr_section; @@ -3274,6 +3272,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } @@ -3289,6 +3288,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } irc_config_section_server_default = ptr_section; @@ -3307,6 +3307,7 @@ irc_config_init () if (!ptr_section) { weechat_config_free (irc_config_file); + irc_config_file = NULL; return 0; } irc_config_section_server = ptr_section; diff --git a/src/plugins/irc/irc-config.h b/src/plugins/irc/irc-config.h index ab745e702..e27313614 100644 --- a/src/plugins/irc/irc-config.h +++ b/src/plugins/irc/irc-config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_CONFIG_H -#define WEECHAT_IRC_CONFIG_H 1 +#ifndef WEECHAT_PLUGIN_IRC_CONFIG_H +#define WEECHAT_PLUGIN_IRC_CONFIG_H #define IRC_CONFIG_NAME "irc" @@ -215,4 +215,4 @@ extern int irc_config_read (); extern int irc_config_write (int write_temp_servers); extern void irc_config_free (); -#endif /* WEECHAT_IRC_CONFIG_H */ +#endif /* WEECHAT_PLUGIN_IRC_CONFIG_H */ diff --git a/src/plugins/irc/irc-ctcp.c b/src/plugins/irc/irc-ctcp.c index 8afee681c..112e842cb 100644 --- a/src/plugins/irc/irc-ctcp.c +++ b/src/plugins/irc/irc-ctcp.c @@ -1,7 +1,7 @@ /* * irc-ctcp.c - IRC CTCP protocol * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -452,9 +452,10 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) now = time (NULL); local_time = localtime (&now); setlocale (LC_ALL, "C"); - strftime (buf, sizeof (buf), - weechat_config_string (irc_config_look_ctcp_time_format), - local_time); + if (strftime (buf, sizeof (buf), + weechat_config_string (irc_config_look_ctcp_time_format), + local_time) == 0) + buf[0] = '\0'; setlocale (LC_ALL, ""); temp = weechat_string_replace (res, "$time", buf); free (res); @@ -466,9 +467,9 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) * $username: user name, example: * name */ - username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME), - NULL, NULL, NULL); + username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME)); if (username) { temp = weechat_string_replace (res, "$username", username); @@ -483,9 +484,9 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) * $realname: real name, example: * John doe */ - realname = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME), - NULL, NULL, NULL); + realname = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME)); if (realname) { temp = weechat_string_replace (res, "$realname", realname); @@ -1084,8 +1085,21 @@ irc_ctcp_recv (struct t_irc_server *server, time_t date, const char *command, address, arguments + 1, pos_args, reply); if (!reply || reply[0]) { - irc_ctcp_reply_to_nick (server, command, channel, nick, - arguments + 1, pos_args); + if (reply) + { + decoded_reply = irc_ctcp_replace_variables (server, reply); + if (decoded_reply) + { + irc_ctcp_reply_to_nick (server, command, channel, nick, + arguments + 1, decoded_reply); + free (decoded_reply); + } + } + else + { + irc_ctcp_reply_to_nick (server, command, channel, nick, + arguments + 1, pos_args); + } } } /* CTCP DCC */ diff --git a/src/plugins/irc/irc-ctcp.h b/src/plugins/irc/irc-ctcp.h index 6fe8b6999..8478bfbe3 100644 --- a/src/plugins/irc/irc-ctcp.h +++ b/src/plugins/irc/irc-ctcp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_CTCP_H -#define WEECHAT_IRC_CTCP_H 1 +#ifndef WEECHAT_PLUGIN_IRC_CTCP_H +#define WEECHAT_PLUGIN_IRC_CTCP_H #include <time.h> @@ -44,4 +44,4 @@ extern void irc_ctcp_recv (struct t_irc_server *server, time_t date, const char *remote_nick, char *arguments, char *message); -#endif /* WEECHAT_IRC_CTCP_H */ +#endif /* WEECHAT_PLUGIN_IRC_CTCP_H */ diff --git a/src/plugins/irc/irc-debug.c b/src/plugins/irc/irc-debug.c index 64e1de89e..79e9ac7f0 100644 --- a/src/plugins/irc/irc-debug.c +++ b/src/plugins/irc/irc-debug.c @@ -1,7 +1,7 @@ /* * irc-debug.c - debug functions for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-debug.h b/src/plugins/irc/irc-debug.h index 5305487df..b7fb094dc 100644 --- a/src/plugins/irc/irc-debug.h +++ b/src/plugins/irc/irc-debug.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_DEBUG_H -#define WEECHAT_IRC_DEBUG_H 1 +#ifndef WEECHAT_PLUGIN_IRC_DEBUG_H +#define WEECHAT_PLUGIN_IRC_DEBUG_H extern void irc_debug_init (); -#endif /* WEECHAT_IRC_DEBUG_H */ +#endif /* WEECHAT_PLUGIN_IRC_DEBUG_H */ diff --git a/src/plugins/irc/irc-ignore.c b/src/plugins/irc/irc-ignore.c index cfc45d6c6..c96777cb0 100644 --- a/src/plugins/irc/irc-ignore.c +++ b/src/plugins/irc/irc-ignore.c @@ -1,7 +1,7 @@ /* * irc-ignore.c - ignore (nicks/hosts) management for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-ignore.h b/src/plugins/irc/irc-ignore.h index 887342cb1..072345f10 100644 --- a/src/plugins/irc/irc-ignore.h +++ b/src/plugins/irc/irc-ignore.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_IGNORE_H -#define WEECHAT_IRC_IGNORE_H 1 +#ifndef WEECHAT_PLUGIN_IRC_IGNORE_H +#define WEECHAT_PLUGIN_IRC_IGNORE_H #include <regex.h> @@ -58,4 +58,4 @@ extern int irc_ignore_add_to_infolist (struct t_infolist *infolist, struct t_irc_ignore *ignore); extern void irc_ignore_print_log (); -#endif /* WEECHAT_IRC_IGNORE_H */ +#endif /* WEECHAT_PLUGIN_IRC_IGNORE_H */ diff --git a/src/plugins/irc/irc-info.c b/src/plugins/irc/irc-info.c index b8dc6f6e1..9ba65334c 100644 --- a/src/plugins/irc/irc-info.c +++ b/src/plugins/irc/irc-info.c @@ -1,7 +1,7 @@ /* * irc-info.c - info, infolist and hdata hooks for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -30,6 +30,7 @@ #include "irc-config.h" #include "irc-ignore.h" #include "irc-message.h" +#include "irc-modelist.h" #include "irc-nick.h" #include "irc-notify.h" #include "irc-protocol.h" @@ -574,6 +575,211 @@ irc_info_infolist_irc_channel_cb (const void *pointer, void *data, } /* + * Returns IRC infolist "irc_modelist". + */ + +struct t_infolist * +irc_info_infolist_irc_modelist_cb (const void *pointer, void *data, + const char *infolist_name, + void *obj_pointer, const char *arguments) +{ + struct t_infolist *ptr_infolist; + struct t_irc_server *ptr_server; + struct t_irc_channel *ptr_channel; + struct t_irc_modelist *ptr_modelist; + char **argv; + int argc; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) infolist_name; + + if (!arguments || !arguments[0]) + return NULL; + + ptr_server = NULL; + ptr_channel = NULL; + argv = weechat_string_split (arguments, ",", 0, 0, &argc); + if (!argv) + return NULL; + + if (argc >= 2) + { + ptr_server = irc_server_search (argv[0]); + if (!ptr_server) + { + weechat_string_free_split (argv); + return NULL; + } + ptr_channel = irc_channel_search (ptr_server, argv[1]); + if (!ptr_channel) + { + weechat_string_free_split (argv); + return NULL; + } + if (!obj_pointer && (argc >= 3)) + { + obj_pointer = irc_modelist_search (ptr_channel, argv[2][0]); + + if (!obj_pointer) + { + weechat_string_free_split (argv); + return NULL; + } + } + } + weechat_string_free_split (argv); + + if (!ptr_server || !ptr_channel) + return NULL; + + if (obj_pointer && !irc_modelist_valid (ptr_channel, obj_pointer)) + return NULL; + + ptr_infolist = weechat_infolist_new (); + if (!ptr_infolist) + return NULL; + + if (obj_pointer) + { + /* build list with only one modelist */ + if (!irc_modelist_add_to_infolist (ptr_infolist, obj_pointer)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + return ptr_infolist; + } + else + { + /* build list with all modelists of channel */ + for (ptr_modelist = ptr_channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + if (!irc_modelist_add_to_infolist (ptr_infolist, ptr_modelist)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + } + return ptr_infolist; + } + + return NULL; +} + +/* + * Returns IRC infolist "irc_modelist_item". + */ + +struct t_infolist * +irc_info_infolist_irc_modelist_item_cb (const void *pointer, void *data, + const char *infolist_name, + void *obj_pointer, const char *arguments) +{ + struct t_infolist *ptr_infolist; + struct t_irc_server *ptr_server; + struct t_irc_channel *ptr_channel; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; + char **argv, *error; + int argc; + long number; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) infolist_name; + + if (!arguments || !arguments[0]) + return NULL; + + ptr_server = NULL; + ptr_channel = NULL; + argv = weechat_string_split (arguments, ",", 0, 0, &argc); + if (!argv) + return NULL; + + if (argc >= 3) + { + ptr_server = irc_server_search (argv[0]); + if (!ptr_server) + { + weechat_string_free_split (argv); + return NULL; + } + ptr_channel = irc_channel_search (ptr_server, argv[1]); + if (!ptr_channel) + { + weechat_string_free_split (argv); + return NULL; + } + ptr_modelist = irc_modelist_search (ptr_channel, argv[2][0]); + if (!ptr_modelist) + { + weechat_string_free_split (argv); + return NULL; + } + if (!obj_pointer && (argc >= 4)) + { + error = NULL; + number = strtol (argv[3], &error, 10); + if (!error || error[0] || (number < 0)) + { + weechat_string_free_split (argv); + return NULL; + } + obj_pointer = irc_modelist_item_search_number (ptr_modelist, + (int)number); + if (!obj_pointer) + { + weechat_string_free_split (argv); + return NULL; + } + } + } + weechat_string_free_split (argv); + + if (!ptr_server || !ptr_channel || !ptr_modelist) + return NULL; + + if (obj_pointer && !irc_modelist_item_valid (ptr_modelist, obj_pointer)) + return NULL; + + ptr_infolist = weechat_infolist_new (); + if (!ptr_infolist) + return NULL; + + if (obj_pointer) + { + /* build list with only one modelist item */ + if (!irc_modelist_item_add_to_infolist (ptr_infolist, obj_pointer)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + return ptr_infolist; + } + else + { + /* build list with all modelist items of modelist */ + for (ptr_item = ptr_modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + if (!irc_modelist_item_add_to_infolist (ptr_infolist, ptr_item)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + } + return ptr_infolist; + } + + return NULL; +} + +/* * Returns IRC infolist "irc_nick". */ @@ -898,7 +1104,7 @@ irc_info_init () &irc_info_info_hashtable_irc_message_parse_cb, NULL, NULL); weechat_hook_info_hashtable ( "irc_message_split", - N_("split an IRC message (to fit in 512 bytes)"), + N_("split an IRC message (to fit in 512 bytes by default)"), N_("\"message\": IRC message, \"server\": server name (optional)"), /* TRANSLATORS: please do not translate key names (enclosed by quotes) */ N_("\"msg1\" ... \"msgN\": messages to send (without final \"\\r\\n\"), " @@ -920,6 +1126,18 @@ irc_info_init () N_("server,channel (channel is optional)"), &irc_info_infolist_irc_channel_cb, NULL, NULL); weechat_hook_infolist ( + "irc_modelist", + N_("list of channel mode lists for an IRC channel"), + N_("mode list pointer (optional)"), + N_("server,channel,type (type is optional)"), + &irc_info_infolist_irc_modelist_cb, NULL, NULL); + weechat_hook_infolist ( + "irc_modelist_item", + N_("list of items in a channel mode list"), + N_("mode list item pointer (optional)"), + N_("server,channel,type,number (number is optional)"), + &irc_info_infolist_irc_modelist_item_cb, NULL, NULL); + weechat_hook_infolist ( "irc_nick", N_("list of nicks for an IRC channel"), N_("nick pointer (optional)"), @@ -949,6 +1167,12 @@ irc_info_init () "irc_nick", N_("irc nick"), &irc_nick_hdata_nick_cb, NULL, NULL); weechat_hook_hdata ( + "irc_modelist", N_("irc modelist"), + &irc_modelist_hdata_modelist_cb, NULL, NULL); + weechat_hook_hdata ( + "irc_modelist_item", N_("irc modelist item"), + &irc_modelist_hdata_item_cb, NULL, NULL); + weechat_hook_hdata ( "irc_channel", N_("irc channel"), &irc_channel_hdata_channel_cb, NULL, NULL); weechat_hook_hdata ( diff --git a/src/plugins/irc/irc-info.h b/src/plugins/irc/irc-info.h index abe44cfb7..765f058c3 100644 --- a/src/plugins/irc/irc-info.h +++ b/src/plugins/irc/irc-info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,9 +17,9 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_INFO_H -#define WEECHAT_IRC_INFO_H 1 +#ifndef WEECHAT_PLUGIN_IRC_INFO_H +#define WEECHAT_PLUGIN_IRC_INFO_H extern void irc_info_init (); -#endif /* WEECHAT_IRC_INFO_H */ +#endif /* WEECHAT_PLUGIN_IRC_INFO_H */ diff --git a/src/plugins/irc/irc-input.c b/src/plugins/irc/irc-input.c index 850642139..e2139c898 100644 --- a/src/plugins/irc/irc-input.c +++ b/src/plugins/irc/irc-input.c @@ -1,7 +1,7 @@ /* * irc-input.c - input data management for IRC buffers * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -139,7 +139,8 @@ irc_input_user_message_display (struct t_gui_buffer *buffer, int action, } /* - * Sends a PRIVMSG message, and split it if message size is > 512 bytes. + * Sends a PRIVMSG message, and split it if message size is > 512 bytes + * (by default). * * Warning: this function makes temporary changes in "message". */ diff --git a/src/plugins/irc/irc-input.h b/src/plugins/irc/irc-input.h index 023aba39d..542340ef1 100644 --- a/src/plugins/irc/irc-input.h +++ b/src/plugins/irc/irc-input.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_INPUT_H -#define WEECHAT_IRC_INPUT_H 1 +#ifndef WEECHAT_PLUGIN_IRC_INPUT_H +#define WEECHAT_PLUGIN_IRC_INPUT_H struct t_gui_buffer; @@ -31,4 +31,4 @@ extern int irc_input_send_cb (const void *pointer, void *data, const char *signal, const char *type_data, void *signal_data); -#endif /* WEECHAT_IRC_INPUT_H */ +#endif /* WEECHAT_PLUGIN_IRC_INPUT_H */ diff --git a/src/plugins/irc/irc-message.c b/src/plugins/irc/irc-message.c index 1d377c701..2df6ab2e8 100644 --- a/src/plugins/irc/irc-message.c +++ b/src/plugins/irc/irc-message.c @@ -1,7 +1,7 @@ /* * irc-message.c - functions for IRC messages * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -20,13 +20,15 @@ */ #include <stdlib.h> +#include <limits.h> #include <stdio.h> #include <string.h> #include "../weechat-plugin.h" #include "irc.h" -#include "irc-server.h" #include "irc-channel.h" +#include "irc-config.h" +#include "irc-server.h" /* @@ -111,9 +113,9 @@ irc_message_parse (struct t_irc_server *server, const char *message, if (ptr_message[0] == '@') { /* - * read tags (they are optional and enabled only if client enabled - * a server capability, see: - * http://ircv3.atheme.org/specification/message-tags-3.2) + * Read tags: they are optional and enabled only if client enabled + * a server capability. + * See: https://ircv3.github.io/specs/core/message-tags-3.2.html */ pos = strchr (ptr_message, ' '); if (pos) @@ -653,13 +655,14 @@ irc_message_split_string (struct t_hashtable *hashtable, const char *arguments, const char *suffix, const char delimiter, - int max_length_host) + int max_length_host, + int max_length) { const char *pos, *pos_max, *pos_next, *pos_last_delim; - char message[1024], *dup_arguments; - int max_length, number; + char message[8192], *dup_arguments; + int number; - max_length = 510; + max_length -= 2; /* by default: 512 - 2 = 510 bytes */ if (max_length_host >= 0) max_length -= max_length_host; else @@ -707,7 +710,7 @@ irc_message_split_string (struct t_hashtable *hashtable, pos = arguments; pos_max = pos + max_length; pos_last_delim = NULL; - while (pos && pos[0]) + while (pos[0]) { if (pos[0] == delimiter) pos_last_delim = pos; @@ -753,12 +756,15 @@ irc_message_split_string (struct t_hashtable *hashtable, int irc_message_split_join (struct t_hashtable *hashtable, const char *tags, const char *host, - const char *arguments) + const char *arguments, + int max_length) { int number, channels_count, keys_count, length, length_no_channel; int length_to_add, index_channel; char **channels, **keys, *pos, *str; - char msg_to_send[2048], keys_to_add[2048]; + char msg_to_send[16384], keys_to_add[16384]; + + max_length -= 2; /* by default: 512 - 2 = 510 bytes */ number = 1; @@ -799,7 +805,8 @@ irc_message_split_join (struct t_hashtable *hashtable, length_to_add = 1 + strlen (channels[index_channel]); if (index_channel < keys_count) length_to_add += 1 + strlen (keys[index_channel]); - if ((length + length_to_add < 510) || (length == length_no_channel)) + if ((length + length_to_add < max_length) + || (length == length_no_channel)) { if (length + length_to_add < (int)sizeof (msg_to_send)) { @@ -864,9 +871,10 @@ int irc_message_split_privmsg_notice (struct t_hashtable *hashtable, char *tags, char *host, char *command, char *target, char *arguments, - int max_length_host) + int max_length_host, + int max_length) { - char prefix[512], suffix[2], *pos, saved_char; + char prefix[4096], suffix[2], *pos, saved_char; int length, rc; /* @@ -903,7 +911,7 @@ irc_message_split_privmsg_notice (struct t_hashtable *hashtable, rc = irc_message_split_string (hashtable, tags, host, command, target, prefix, arguments, suffix, - ' ', max_length_host); + ' ', max_length_host, max_length); return rc; } @@ -919,9 +927,9 @@ irc_message_split_privmsg_notice (struct t_hashtable *hashtable, int irc_message_split_005 (struct t_hashtable *hashtable, char *tags, char *host, char *command, char *target, - char *arguments) + char *arguments, int max_length) { - char *pos, suffix[512]; + char *pos, suffix[4096]; /* * 005 message looks like: @@ -941,7 +949,8 @@ irc_message_split_005 (struct t_hashtable *hashtable, } return irc_message_split_string (hashtable, tags, host, command, target, - NULL, arguments, suffix, ' ', -1); + NULL, arguments, suffix, ' ', -1, + max_length); } /* @@ -951,6 +960,10 @@ irc_message_split_005 (struct t_hashtable *hashtable, * "\r\n", so full size is 512 bytes (the user data does not include the * optional tags before the host). * + * The 512 max length is the default (recommended) and can be changed with the + * server option called "split_msg_max_length" (0 to disable completely the + * split). + * * The split takes care about type of message to do a split at best place in * message. * @@ -972,9 +985,10 @@ struct t_hashtable * irc_message_split (struct t_irc_server *server, const char *message) { struct t_hashtable *hashtable; - char **argv, **argv_eol, *tags, *host, *command, *arguments, target[512]; + char **argv, **argv_eol, *tags, *host, *command, *arguments, target[4096]; char *pos, monitor_action[3]; int split_ok, argc, index_args, max_length_nick, max_length_host; + int split_msg_max_length; split_ok = 0; tags = NULL; @@ -984,9 +998,29 @@ irc_message_split (struct t_irc_server *server, const char *message) argv = NULL; argv_eol = NULL; + if (server) + { + split_msg_max_length = IRC_SERVER_OPTION_INTEGER( + server, IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH); + + /* + * split disabled? use a very high max_length so the message should + * never be split + */ + if (split_msg_max_length == 0) + split_msg_max_length = INT_MAX - 16; + } + else + { + split_msg_max_length = 512; /* max length by default */ + } + /* debug message */ if (weechat_irc_plugin->debug >= 2) - weechat_printf (NULL, "irc_message_split: message='%s'", message); + { + weechat_printf (NULL, "irc_message_split: message='%s', max length=%d", + message, split_msg_max_length); + } hashtable = weechat_hashtable_new (32, WEECHAT_HASHTABLE_STRING, @@ -1049,7 +1083,7 @@ irc_message_split (struct t_irc_server *server, const char *message) hashtable, tags, host, command, NULL, ":", (argv_eol[index_args][0] == ':') ? argv_eol[index_args] + 1 : argv_eol[index_args], - NULL, ' ', max_length_host); + NULL, ' ', max_length_host, split_msg_max_length); } else if (weechat_strcasecmp (command, "monitor") == 0) { @@ -1064,7 +1098,8 @@ irc_message_split (struct t_irc_server *server, const char *message) "%c ", argv_eol[index_args][0]); split_ok = irc_message_split_string ( hashtable, tags, host, command, NULL, monitor_action, - argv_eol[index_args] + 2, NULL, ',', max_length_host); + argv_eol[index_args] + 2, NULL, ',', max_length_host, + split_msg_max_length); } else { @@ -1072,17 +1107,17 @@ irc_message_split (struct t_irc_server *server, const char *message) hashtable, tags, host, command, NULL, ":", (argv_eol[index_args][0] == ':') ? argv_eol[index_args] + 1 : argv_eol[index_args], - NULL, ',', max_length_host); + NULL, ',', max_length_host, split_msg_max_length); } } else if (weechat_strcasecmp (command, "join") == 0) { /* JOIN #channel1,#channel2,#channel3 key1,key2 */ - if (strlen (message) > 510) + if ((int)strlen (message) > split_msg_max_length - 2) { - /* split join if it's more than 510 bytes */ + /* split join if it's too long */ split_ok = irc_message_split_join (hashtable, tags, host, - arguments); + arguments, split_msg_max_length); } } else if ((weechat_strcasecmp (command, "privmsg") == 0) @@ -1098,7 +1133,7 @@ irc_message_split (struct t_irc_server *server, const char *message) hashtable, tags, host, command, argv[index_args], (argv_eol[index_args + 1][0] == ':') ? argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1], - max_length_host); + max_length_host, split_msg_max_length); } } else if (weechat_strcasecmp (command, "005") == 0) @@ -1109,7 +1144,8 @@ irc_message_split (struct t_irc_server *server, const char *message) split_ok = irc_message_split_005 ( hashtable, tags, host, command, argv[index_args], (argv_eol[index_args + 1][0] == ':') ? - argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1]); + argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1], + split_msg_max_length); } } else if (weechat_strcasecmp (command, "353") == 0) @@ -1128,7 +1164,7 @@ irc_message_split (struct t_irc_server *server, const char *message) hashtable, tags, host, command, target, ":", (argv_eol[index_args + 2][0] == ':') ? argv_eol[index_args + 2] + 1 : argv_eol[index_args + 2], - NULL, ' ', -1); + NULL, ' ', -1, split_msg_max_length); } else { @@ -1141,7 +1177,7 @@ irc_message_split (struct t_irc_server *server, const char *message) hashtable, tags, host, command, target, ":", (argv_eol[index_args + 3][0] == ':') ? argv_eol[index_args + 3] + 1 : argv_eol[index_args + 3], - NULL, ' ', -1); + NULL, ' ', -1, split_msg_max_length); } } } diff --git a/src/plugins/irc/irc-message.h b/src/plugins/irc/irc-message.h index b1fa63e30..cbf2d331d 100644 --- a/src/plugins/irc/irc-message.h +++ b/src/plugins/irc/irc-message.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_MESSAGE_H -#define WEECHAT_IRC_MESSAGE_H 1 +#ifndef WEECHAT_PLUGIN_IRC_MESSAGE_H +#define WEECHAT_PLUGIN_IRC_MESSAGE_H struct t_irc_server; struct t_irc_channel; @@ -43,4 +43,4 @@ extern char *irc_message_replace_vars (struct t_irc_server *server, extern struct t_hashtable *irc_message_split (struct t_irc_server *server, const char *message); -#endif /* WEECHAT_IRC_MESSAGE_H */ +#endif /* WEECHAT_PLUGIN_IRC_MESSAGE_H */ diff --git a/src/plugins/irc/irc-mode.c b/src/plugins/irc/irc-mode.c index d828a13a4..b5d525c6c 100644 --- a/src/plugins/irc/irc-mode.c +++ b/src/plugins/irc/irc-mode.c @@ -1,7 +1,7 @@ /* * irc-mode.c - IRC channel/user modes management * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -22,6 +22,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <time.h> #include "../weechat-plugin.h" #include "irc.h" @@ -30,6 +31,7 @@ #include "irc-server.h" #include "irc-channel.h" #include "irc-nick.h" +#include "irc-modelist.h" /* @@ -317,12 +319,15 @@ irc_mode_smart_filtered (struct t_irc_server *server, char mode) int irc_mode_channel_set (struct t_irc_server *server, struct t_irc_channel *channel, + const char *host, const char *modes) { char *pos_args, *str_modes, set_flag, **argv, *pos, *ptr_arg, chanmode_type; int argc, current_arg, update_channel_modes, channel_modes_updated; int smart_filter; struct t_irc_nick *ptr_nick; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; if (!server || !channel || !modes) return 0; @@ -464,6 +469,27 @@ irc_mode_channel_set (struct t_irc_server *server, } } } + else if (chanmode_type == 'A') + { + /* modelist modes */ + ptr_modelist = irc_modelist_search (channel, pos[0]); + if (ptr_modelist) + { + if (set_flag == '+') + { + irc_modelist_item_new (ptr_modelist, ptr_arg, + host, time (NULL)); + } + else if (set_flag == '-') + { + ptr_item = irc_modelist_item_search_mask ( + ptr_modelist, ptr_arg); + if (ptr_item) + irc_modelist_item_free (ptr_modelist, ptr_item); + } + } + } + if (update_channel_modes) { irc_mode_channel_update (server, channel, set_flag, diff --git a/src/plugins/irc/irc-mode.h b/src/plugins/irc/irc-mode.h index 03313d983..857a8a8fc 100644 --- a/src/plugins/irc/irc-mode.h +++ b/src/plugins/irc/irc-mode.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_MODE_H -#define WEECHAT_IRC_MODE_H 1 +#ifndef WEECHAT_PLUGIN_IRC_MODE_H +#define WEECHAT_PLUGIN_IRC_MODE_H struct t_irc_server; struct t_irc_channel; @@ -27,8 +27,9 @@ extern char irc_mode_get_chanmode_type (struct t_irc_server *server, char chanmode); extern int irc_mode_channel_set (struct t_irc_server *server, struct t_irc_channel *channel, + const char *host, const char *modes); extern void irc_mode_user_set (struct t_irc_server *server, const char *modes, int reset_modes); -#endif /* WEECHAT_IRC_MODE_H */ +#endif /* WEECHAT_PLUGIN_IRC_MODE_H */ diff --git a/src/plugins/irc/irc-modelist.c b/src/plugins/irc/irc-modelist.c new file mode 100644 index 000000000..d21b34971 --- /dev/null +++ b/src/plugins/irc/irc-modelist.c @@ -0,0 +1,505 @@ +/* + * irc-modelist.c - channel mode list management for IRC plugin + * + * Copyright (C) 2015 Simmo Saan <simmo.saan@gmail.com> + * Copyright (C) 2018 Sébastien 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/>. + */ + +#include <stdlib.h> +#include <stddef.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "../weechat-plugin.h" +#include "irc.h" +#include "irc-channel.h" +#include "irc-modelist.h" + + +/* + * Checks if a modelist pointer is valid for a channel. + * + * Returns: + * 1: modelist exists for channel + * 0: modelist does not exist for channel + */ + +int +irc_modelist_valid (struct t_irc_channel *channel, + struct t_irc_modelist *modelist) +{ + struct t_irc_modelist *ptr_modelist; + + if (!channel || !modelist) + return 0; + + for (ptr_modelist = channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + if (ptr_modelist == modelist) + return 1; + } + + /* modelist not found */ + return 0; +} + +/* + * Searches for a modelist by type. + * + * Returns pointer to modelist found, NULL if not found. + */ + +struct t_irc_modelist * +irc_modelist_search (struct t_irc_channel *channel, char type) +{ + struct t_irc_modelist *ptr_modelist; + + if (!channel) + return NULL; + + for (ptr_modelist = channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + if (ptr_modelist->type == type) + return ptr_modelist; + } + return NULL; +} + +/* + * Creates a new modelist in a channel. + * + * Returns pointer to new modelist, NULL if error. + */ + +struct t_irc_modelist * +irc_modelist_new (struct t_irc_channel *channel, char type) +{ + struct t_irc_modelist *new_modelist; + + /* alloc memory for new modelist */ + if ((new_modelist = malloc (sizeof (*new_modelist))) == NULL) + { + weechat_printf (NULL, + _("%s%s: cannot allocate new modelist"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + return NULL; + } + + /* initialize new modelist */ + new_modelist->type = type; + new_modelist->state = IRC_MODELIST_STATE_EMPTY; + new_modelist->items = NULL; + new_modelist->last_item = NULL; + + /* add new modelist to channel */ + new_modelist->prev_modelist = channel->last_modelist; + new_modelist->next_modelist = NULL; + if (channel->modelists) + (channel->last_modelist)->next_modelist = new_modelist; + else + channel->modelists = new_modelist; + channel->last_modelist = new_modelist; + + /* all is OK, return address of new modelist */ + return new_modelist; +} + +/* + * Frees a modelist and remove it from channel. + */ + +void +irc_modelist_free (struct t_irc_channel *channel, + struct t_irc_modelist *modelist) +{ + struct t_irc_modelist *new_modelists; + + if (!channel || !modelist) + return; + + /* remove modelist from channel modelists */ + if (channel->last_modelist == modelist) + channel->last_modelist = modelist->prev_modelist; + if (modelist->prev_modelist) + { + (modelist->prev_modelist)->next_modelist = modelist->next_modelist; + new_modelists = channel->modelists; + } + else + new_modelists = modelist->next_modelist; + + if (modelist->next_modelist) + (modelist->next_modelist)->prev_modelist = modelist->prev_modelist; + + /* free linked lists */ + irc_modelist_item_free_all (modelist); + + free (modelist); + + channel->modelists = new_modelists; +} + +/* + * Frees all modelists for a channel. + */ + +void +irc_modelist_free_all (struct t_irc_channel *channel) +{ + while (channel->modelists) + { + irc_modelist_free (channel, channel->modelists); + } +} + +/* + * Checks if a modelist item pointer is valid for a modelist. + * + * Returns: + * 1: item exists for modelist + * 0: item does not exist for modelist + */ + +int +irc_modelist_item_valid (struct t_irc_modelist *modelist, + struct t_irc_modelist_item *item) +{ + struct t_irc_modelist_item *ptr_item; + + if (!modelist || !item) + return 0; + + for (ptr_item = modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + if (ptr_item == item) + return 1; + } + + /* item not found */ + return 0; +} + +/* + * Searches for an item by mask. + * + * Returns pointer to item found, NULL if not found. + */ + +struct t_irc_modelist_item * +irc_modelist_item_search_mask (struct t_irc_modelist *modelist, const char *mask) +{ + struct t_irc_modelist_item *ptr_item; + + if (!modelist || !mask) + return NULL; + + for (ptr_item = modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + if (strcmp (ptr_item->mask, mask) == 0) + return ptr_item; + } + return NULL; +} + +/* + * Searches for an item by number. + * + * Returns pointer to item found, NULL if not found. + */ + +struct t_irc_modelist_item * +irc_modelist_item_search_number (struct t_irc_modelist *modelist, int number) +{ + struct t_irc_modelist_item *ptr_item; + + if (!modelist) + return NULL; + + for (ptr_item = modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + if (ptr_item->number == number) + return ptr_item; + } + return NULL; +} + +/* + * Creates a new item in a modelist. + * + * Returns pointer to new item, NULL if error. + */ + +struct t_irc_modelist_item * +irc_modelist_item_new (struct t_irc_modelist *modelist, + const char *mask, const char *setter, time_t datetime) +{ + struct t_irc_modelist_item *new_item; + + /* alloc memory for new item */ + if ((new_item = malloc (sizeof (*new_item))) == NULL) + { + weechat_printf (NULL, + _("%s%s: cannot allocate new modelist item"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + return NULL; + } + + /* initialize new item */ + new_item->number = (modelist->last_item) ? + modelist->last_item->number + 1 : 0; + new_item->mask = strdup (mask); + new_item->setter = (setter) ? strdup (setter) : NULL; + new_item->datetime = datetime; + + /* add new item to modelist */ + new_item->prev_item = modelist->last_item; + new_item->next_item = NULL; + if (modelist->items) + (modelist->last_item)->next_item = new_item; + else + modelist->items = new_item; + modelist->last_item = new_item; + + if ((modelist->state == IRC_MODELIST_STATE_EMPTY) || + (modelist->state == IRC_MODELIST_STATE_RECEIVED)) + { + modelist->state = IRC_MODELIST_STATE_MODIFIED; + } + + /* all is OK, return address of new item */ + return new_item; +} + +/* + * Frees an item and remove it from modelist. + */ + +void +irc_modelist_item_free (struct t_irc_modelist *modelist, + struct t_irc_modelist_item *item) +{ + struct t_irc_modelist_item *new_items; + + if (!modelist || !item) + return; + + /* remove item from modelist list */ + if (modelist->last_item == item) + modelist->last_item = item->prev_item; + if (item->prev_item) + { + (item->prev_item)->next_item = item->next_item; + new_items = modelist->items; + } + else + new_items = item->next_item; + + if (item->next_item) + (item->next_item)->prev_item = item->prev_item; + + /* free item data */ + if (item->mask) + free (item->mask); + if (item->setter) + free (item->setter); + free (item); + + modelist->items = new_items; + + if (modelist->state == IRC_MODELIST_STATE_RECEIVED) + modelist->state = IRC_MODELIST_STATE_MODIFIED; +} + +/* + * Frees all items for a modelist. + */ + +void +irc_modelist_item_free_all (struct t_irc_modelist *modelist) +{ + while (modelist->items) + { + irc_modelist_item_free (modelist, modelist->items); + } + modelist->state = IRC_MODELIST_STATE_EMPTY; +} + +/* + * Returns hdata for modelist item. + */ + +struct t_hdata * +irc_modelist_hdata_item_cb (const void *pointer, void *data, + const char *hdata_name) +{ + struct t_hdata *hdata; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + hdata = weechat_hdata_new (hdata_name, "prev_item", "next_item", + 0, 0, NULL, NULL); + if (hdata) + { + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, number, INTEGER, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, mask, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, setter, STRING, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, datetime, TIME, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, prev_item, POINTER, 0, NULL, hdata_name); + WEECHAT_HDATA_VAR(struct t_irc_modelist_item, next_item, POINTER, 0, NULL, hdata_name); + } + return hdata; +} + +/* + * Returns hdata for modelist. + */ + +struct t_hdata * +irc_modelist_hdata_modelist_cb (const void *pointer, void *data, const char *hdata_name) +{ + struct t_hdata *hdata; + + /* make C compiler happy */ + (void) pointer; + (void) data; + + hdata = weechat_hdata_new (hdata_name, "prev_modelist", "next_modelist", + 0, 0, NULL, NULL); + if (hdata) + { + WEECHAT_HDATA_VAR(struct t_irc_modelist, type, CHAR, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist, state, INTEGER, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_modelist, items, POINTER, 0, NULL, "irc_modelist_item"); + WEECHAT_HDATA_VAR(struct t_irc_modelist, last_item, POINTER, 0, NULL, "irc_modelist_item"); + WEECHAT_HDATA_VAR(struct t_irc_modelist, prev_modelist, POINTER, 0, NULL, hdata_name); + WEECHAT_HDATA_VAR(struct t_irc_modelist, next_modelist, POINTER, 0, NULL, hdata_name); + } + return hdata; +} + +/* + * Adds a modelist item in an infolist. + * + * Returns: + * 1: OK + * 0: error + */ + +int +irc_modelist_item_add_to_infolist (struct t_infolist *infolist, + struct t_irc_modelist_item *item) +{ + struct t_infolist_item *ptr_item; + + if (!infolist || !item) + return 0; + + ptr_item = weechat_infolist_new_item (infolist); + if (!ptr_item) + return 0; + + if (!weechat_infolist_new_var_integer (ptr_item, "number", item->number)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "mask", item->mask)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "setter", item->setter)) + return 0; + if (!weechat_infolist_new_var_time (ptr_item, "datetime", item->datetime)) + return 0; + + return 1; +} + +/* + * Adds a modelist in an infolist. + * + * Returns: + * 1: OK + * 0: error + */ + +int +irc_modelist_add_to_infolist (struct t_infolist *infolist, + struct t_irc_modelist *modelist) +{ + struct t_infolist_item *ptr_item; + char str_type[2]; + + if (!infolist || !modelist) + return 0; + + ptr_item = weechat_infolist_new_item (infolist); + if (!ptr_item) + return 0; + + str_type[0] = modelist->type; + str_type[1] = '\0'; + + if (!weechat_infolist_new_var_string (ptr_item, "type", str_type)) + return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "state", modelist->state)) + return 0; + + return 1; +} + +/* + * Prints modelist item infos in WeeChat log file (usually for crash dump). + */ + +void +irc_modelist_item_print_log (struct t_irc_modelist_item *item) +{ + weechat_log_printf (""); + weechat_log_printf (" => modelist item %d (addr:0x%lx):", item->number, item); + weechat_log_printf (" mask . . . . . . . . . . : '%s'", item->mask); + weechat_log_printf (" setter . . . . . . . . . : '%s'", item->setter); + weechat_log_printf (" datetime . . . . . . . . : %lld", + (long long)(item->datetime)); + weechat_log_printf (" prev_item . . . . . . . : 0x%lx", item->prev_item); + weechat_log_printf (" next_item . . . . . . . : 0x%lx", item->next_item); +} + +/* + * Prints modelist infos in WeeChat log file (usually for crash dump). + */ + +void +irc_modelist_print_log (struct t_irc_modelist *modelist) +{ + struct t_irc_modelist_item *ptr_item; + + weechat_log_printf (""); + weechat_log_printf (" => modelist \"%c\" (addr:0x%lx):", modelist->type, modelist); + weechat_log_printf (" state. . . . . . . . . . : %d", modelist->state); + weechat_log_printf (" prev_modelist . . . . . : 0x%lx", modelist->prev_modelist); + weechat_log_printf (" next_modelist . . . . . : 0x%lx", modelist->next_modelist); + for (ptr_item = modelist->items; ptr_item; ptr_item = ptr_item->next_item) + { + irc_modelist_item_print_log (ptr_item); + } +} diff --git a/src/plugins/irc/irc-modelist.h b/src/plugins/irc/irc-modelist.h new file mode 100644 index 000000000..1648ef9eb --- /dev/null +++ b/src/plugins/irc/irc-modelist.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2015 Simmo Saan <simmo.saan@gmail.com> + * Copyright (C) 2018 Sébastien 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_PLUGIN_IRC_MODELIST_H +#define WEECHAT_PLUGIN_IRC_MODELIST_H + +#include <time.h> + +/* modelist states */ +#define IRC_MODELIST_STATE_EMPTY 0 +#define IRC_MODELIST_STATE_RECEIVING 1 +#define IRC_MODELIST_STATE_RECEIVED 2 +#define IRC_MODELIST_STATE_MODIFIED 3 + +struct t_irc_server; + +struct t_irc_modelist_item +{ + int number; /* item number */ + char *mask; /* modelist mask */ + char *setter; /* hostmask of setter (optional) */ + time_t datetime; /* datetime of setting (optional)*/ + + struct t_irc_modelist_item *prev_item; /* pointer to previous item */ + struct t_irc_modelist_item *next_item; /* pointer to next item */ +}; + +struct t_irc_modelist +{ + char type; /* mode list channel A type */ + int state; /* state */ + + struct t_irc_modelist_item *items; /* items in modelist */ + struct t_irc_modelist_item *last_item; /* last item in modelist */ + + struct t_irc_modelist *prev_modelist; /* pointer to previous modelist */ + struct t_irc_modelist *next_modelist; /* pointer to next modelist */ +}; + +extern int irc_modelist_valid (struct t_irc_channel *channel, + struct t_irc_modelist *modelist); +extern struct t_irc_modelist *irc_modelist_search (struct t_irc_channel *channel, + char type); +extern struct t_irc_modelist *irc_modelist_new (struct t_irc_channel *channel, + char type); +extern void irc_modelist_free (struct t_irc_channel *channel, + struct t_irc_modelist *modelist); +extern void irc_modelist_free_all (struct t_irc_channel *channel); + +extern int irc_modelist_item_valid (struct t_irc_modelist *modelist, + struct t_irc_modelist_item *item); +extern struct t_irc_modelist_item *irc_modelist_item_search_mask (struct t_irc_modelist *modelist, + const char *mask); +extern struct t_irc_modelist_item *irc_modelist_item_search_number (struct t_irc_modelist *modelist, + int number); +extern struct t_irc_modelist_item *irc_modelist_item_new (struct t_irc_modelist *modelist, + const char *mask, + const char *setter, + time_t datetime); +extern void irc_modelist_item_free (struct t_irc_modelist *modelist, + struct t_irc_modelist_item *item); +extern void irc_modelist_item_free_all (struct t_irc_modelist *modelist); + +extern struct t_hdata *irc_modelist_hdata_item_cb (const void *pointer, + void *data, + const char *hdata_name); +extern struct t_hdata *irc_modelist_hdata_modelist_cb (const void *pointer, + void *data, + const char *hdata_name); +extern int irc_modelist_item_add_to_infolist (struct t_infolist *infolist, + struct t_irc_modelist_item *item); +extern int irc_modelist_add_to_infolist (struct t_infolist *infolist, + struct t_irc_modelist *modelist); +extern void irc_modelist_item_print_log (struct t_irc_modelist_item *item); +extern void irc_modelist_print_log (struct t_irc_modelist *modelist); + +#endif /* WEECHAT_PLUGIN_IRC_MODELIST_H */ diff --git a/src/plugins/irc/irc-msgbuffer.c b/src/plugins/irc/irc-msgbuffer.c index 21339e7bc..ad57ecdb2 100644 --- a/src/plugins/irc/irc-msgbuffer.c +++ b/src/plugins/irc/irc-msgbuffer.c @@ -1,7 +1,7 @@ /* * irc-msgbuffer.c - target buffer for IRC messages * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-msgbuffer.h b/src/plugins/irc/irc-msgbuffer.h index c2e72fe05..c96bfa23a 100644 --- a/src/plugins/irc/irc-msgbuffer.h +++ b/src/plugins/irc/irc-msgbuffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_MSGBUFFER_H -#define WEECHAT_IRC_MSGBUFFER_H 1 +#ifndef WEECHAT_PLUGIN_IRC_MSGBUFFER_H +#define WEECHAT_PLUGIN_IRC_MSGBUFFER_H enum t_irc_msgbuffer_target { @@ -38,4 +38,4 @@ extern struct t_gui_buffer *irc_msgbuffer_get_target_buffer (struct t_irc_server const char *alias, struct t_gui_buffer *default_buffer); -#endif /* WEECHAT_IRC_MSGBUFFER_H */ +#endif /* WEECHAT_PLUGIN_IRC_MSGBUFFER_H */ diff --git a/src/plugins/irc/irc-nick.c b/src/plugins/irc/irc-nick.c index 6559fc2ca..22e89da26 100644 --- a/src/plugins/irc/irc-nick.c +++ b/src/plugins/irc/irc-nick.c @@ -1,7 +1,7 @@ /* * irc-nick.c - nick management for IRC plugin * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -320,7 +320,7 @@ irc_nick_get_color_for_nicklist (struct t_irc_server *server, if (nick->away) return nick_color_away; - if (weechat_config_boolean(irc_config_look_color_nicks_in_nicklist)) + if (weechat_config_boolean (irc_config_look_color_nicks_in_nicklist)) { if (irc_server_strcasecmp (server, nick->name, server->nick) == 0) return nick_color_self; @@ -470,15 +470,8 @@ irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, /* remove old nick from nicklist */ irc_nick_nicklist_remove (server, channel, ptr_nick); - /* update nick */ + /* update nick prefixes */ irc_nick_set_prefixes (server, ptr_nick, prefixes); - ptr_nick->away = away; - if (ptr_nick->account) - free (ptr_nick->account); - ptr_nick->account = (account) ? strdup (account) : NULL; - if (ptr_nick->realname) - free (ptr_nick->realname); - ptr_nick->realname = (realname) ? strdup (realname) : NULL; /* add new nick in nicklist */ irc_nick_nicklist_add (server, channel, ptr_nick); @@ -497,7 +490,8 @@ irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, new_nick->realname = (realname) ? strdup (realname) : NULL; length = strlen (irc_server_get_prefix_chars (server)); new_nick->prefixes = malloc (length + 1); - if (!new_nick->name || !new_nick->prefixes) + new_nick->prefix = malloc (2); + if (!new_nick->name || !new_nick->prefixes || !new_nick->prefix) { if (new_nick->name) free (new_nick->name); @@ -509,14 +503,13 @@ irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, free (new_nick->realname); if (new_nick->prefixes) free (new_nick->prefixes); + if (new_nick->prefix) + free (new_nick->prefix); free (new_nick); return NULL; } - if (new_nick->prefixes) - { - memset (new_nick->prefixes, ' ', length); - new_nick->prefixes[length] = '\0'; - } + memset (new_nick->prefixes, ' ', length); + new_nick->prefixes[length] = '\0'; new_nick->prefix[0] = ' '; new_nick->prefix[1] = '\0'; irc_nick_set_prefixes (server, new_nick, prefixes); @@ -647,6 +640,8 @@ irc_nick_free (struct t_irc_server *server, struct t_irc_channel *channel, free (nick->host); if (nick->prefixes) free (nick->prefixes); + if (nick->prefix) + free (nick->prefix); if (nick->account) free (nick->account); if (nick->realname) @@ -754,18 +749,11 @@ void irc_nick_set_away (struct t_irc_server *server, struct t_irc_channel *channel, struct t_irc_nick *nick, int is_away) { - if (!is_away - || weechat_hashtable_has_key (server->cap_list, "away-notify") - || ((IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK) > 0) - && ((IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS) == 0) - || (channel->nicks_count <= IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS))))) + if (is_away != nick->away) { - if ((is_away && !nick->away) || (!is_away && nick->away)) - { - nick->away = is_away; - irc_nick_nicklist_set (channel, nick, "color", - irc_nick_get_color_for_nicklist (server, nick)); - } + nick->away = is_away; + irc_nick_nicklist_set (channel, nick, "color", + irc_nick_get_color_for_nicklist (server, nick)); } } diff --git a/src/plugins/irc/irc-nick.h b/src/plugins/irc/irc-nick.h index f67ee6656..92ef6f199 100644 --- a/src/plugins/irc/irc-nick.h +++ b/src/plugins/irc/irc-nick.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_NICK_H -#define WEECHAT_IRC_NICK_H 1 +#ifndef WEECHAT_PLUGIN_IRC_NICK_H +#define WEECHAT_PLUGIN_IRC_NICK_H #define IRC_NICK_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHI" \ "JKLMNOPQRSTUVWXYZ0123456789-[]\\`_^{|}" @@ -35,8 +35,8 @@ struct t_irc_nick char *name; /* nickname */ char *host; /* full hostname */ char *prefixes; /* string with prefixes enabled for nick */ - char prefix[2]; /* current prefix (higher prefix set in */ - /* prefixes) */ + char *prefix; /* current prefix (higher prefix set in */ + /* prefixes); string with just one char */ int away; /* 1 if nick is away */ char *account; /* account name of the user */ char *realname; /* realname (aka gecos) of the user */ @@ -109,4 +109,4 @@ extern int irc_nick_add_to_infolist (struct t_infolist *infolist, struct t_irc_nick *nick); extern void irc_nick_print_log (struct t_irc_nick *nick); -#endif /* WEECHAT_IRC_NICK_H */ +#endif /* WEECHAT_PLUGIN_IRC_NICK_H */ diff --git a/src/plugins/irc/irc-notify.c b/src/plugins/irc/irc-notify.c index 579046b29..be847c100 100644 --- a/src/plugins/irc/irc-notify.c +++ b/src/plugins/irc/irc-notify.c @@ -1,7 +1,7 @@ /* * irc-notify.c - notify lists for IRC plugin * - * Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2010-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-notify.h b/src/plugins/irc/irc-notify.h index 0f6778b7e..81322778c 100644 --- a/src/plugins/irc/irc-notify.h +++ b/src/plugins/irc/irc-notify.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2010-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_NOTIFY_H -#define WEECHAT_IRC_NOTIFY_H 1 +#ifndef WEECHAT_PLUGIN_IRC_NOTIFY_H +#define WEECHAT_PLUGIN_IRC_NOTIFY_H struct t_irc_server; @@ -75,4 +75,4 @@ extern void irc_notify_hook_timer_whois (); extern void irc_notify_init (); extern void irc_notify_end (); -#endif /* WEECHAT_IRC_NOTIFY_H */ +#endif /* WEECHAT_PLUGIN_IRC_NOTIFY_H */ diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c index 1b4fce045..340eb6589 100644 --- a/src/plugins/irc/irc-protocol.c +++ b/src/plugins/irc/irc-protocol.c @@ -1,7 +1,7 @@ /* * irc-protocol.c - implementation of IRC protocol (RFCs 1459/2810/2811/2812/2813) * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> * Copyright (C) 2014 Shawn Smith <ShawnSmith0828@gmail.com> * @@ -50,6 +50,7 @@ #include "irc-ignore.h" #include "irc-message.h" #include "irc-mode.h" +#include "irc-modelist.h" #include "irc-msgbuffer.h" #include "irc-nick.h" #include "irc-sasl.h" @@ -252,12 +253,12 @@ IRC_PROTOCOL_CALLBACK(authenticate) { sasl_mechanism = IRC_SERVER_OPTION_INTEGER( server, IRC_SERVER_OPTION_SASL_MECHANISM); - sasl_username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME), - NULL, NULL, NULL); - sasl_password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD), - NULL, NULL, NULL); + sasl_username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME)); + sasl_password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD)); sasl_key = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_KEY); answer = NULL; switch (sasl_mechanism) @@ -697,7 +698,7 @@ IRC_PROTOCOL_CALLBACK(cap) snprintf (str_msg_auth, sizeof (str_msg_auth), "AUTHENTICATE %s", irc_sasl_mechanism_string[sasl_mechanism]); - weechat_string_toupper(str_msg_auth); + weechat_string_toupper (str_msg_auth); irc_server_sendf (server, 0, NULL, str_msg_auth); if (server->hook_timer_sasl) weechat_unhook (server->hook_timer_sasl); @@ -1162,6 +1163,9 @@ IRC_PROTOCOL_CALLBACK(kick) */ irc_nick_free_all (server, ptr_channel); + irc_channel_modelist_set_state (ptr_channel, + IRC_MODELIST_STATE_MODIFIED); + /* read option "autorejoin" in server */ rejoin = IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOREJOIN); @@ -1276,6 +1280,9 @@ IRC_PROTOCOL_CALLBACK(kill) */ irc_nick_free_all (server, ptr_channel); + irc_channel_modelist_set_state (ptr_channel, + IRC_MODELIST_STATE_MODIFIED); + irc_bar_item_update_channel (); } else @@ -1318,7 +1325,7 @@ IRC_PROTOCOL_CALLBACK(mode) ptr_channel = irc_channel_search (server, argv[2]); if (ptr_channel) { - smart_filter = irc_mode_channel_set (server, ptr_channel, + smart_filter = irc_mode_channel_set (server, ptr_channel, host, pos_modes); } local_mode = (irc_server_strcasecmp (server, nick, server->nick) == 0); @@ -1504,7 +1511,7 @@ IRC_PROTOCOL_CALLBACK(nick) address), _("%s%s%s%s is now known as %s%s%s"), weechat_prefix ("network"), - weechat_config_boolean(irc_config_look_color_nicks_in_server_messages) ? + weechat_config_boolean (irc_config_look_color_nicks_in_server_messages) ? old_color : IRC_COLOR_CHAT_NICK, nick, IRC_COLOR_RESET, @@ -1913,6 +1920,9 @@ IRC_PROTOCOL_CALLBACK(part) { irc_nick_free_all (server, ptr_channel); + irc_channel_modelist_set_state (ptr_channel, + IRC_MODELIST_STATE_MODIFIED); + /* cycling ? => rejoin channel immediately */ if (ptr_channel->cycle) { @@ -2652,9 +2662,9 @@ IRC_PROTOCOL_CALLBACK(001) WEECHAT_HOOK_SIGNAL_STRING, server->name); /* set usermode when connected */ - usermode = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERMODE), - NULL, NULL, NULL); + usermode = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERMODE)); if (usermode && usermode[0]) { irc_server_sendf (server, @@ -2666,9 +2676,9 @@ IRC_PROTOCOL_CALLBACK(001) free (usermode); /* execute command when connected */ - server_command = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_COMMAND), - NULL, NULL, NULL); + server_command = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_COMMAND)); if (server_command && server_command[0]) { /* split command on ';' which can be escaped with '\;' */ @@ -3450,7 +3460,7 @@ IRC_PROTOCOL_CALLBACK(324) irc_channel_set_modes (ptr_channel, ptr_modes); if (argc > 4) { - (void) irc_mode_channel_set (server, ptr_channel, + (void) irc_mode_channel_set (server, ptr_channel, host, ptr_channel->modes); } } @@ -4034,14 +4044,36 @@ IRC_PROTOCOL_CALLBACK(346) { struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; time_t datetime; const char *nick_address; + char str_number[64]; IRC_PROTOCOL_MIN_ARGS(5); ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'I'); + + if (ptr_modelist) + { + /* start receiving new list */ + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + irc_modelist_item_free_all (ptr_modelist); + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVING; + } + + sprintf (str_number, "%s[%s%d%s] ", + IRC_COLOR_CHAT_DELIMITERS, + IRC_COLOR_RESET, + ((ptr_modelist->last_item) ? ptr_modelist->last_item->number + 1 : 0) + 1, + IRC_COLOR_CHAT_DELIMITERS); + } + else + str_number[0] = '\0'; + if (argc >= 6) { nick_address = irc_protocol_nick_address ( @@ -4050,18 +4082,21 @@ IRC_PROTOCOL_CALLBACK(346) if (argc >= 7) { datetime = (time_t)(atol (argv[6])); + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], datetime); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "invitelist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), /* TRANSLATORS: "%s" after "on" is a date */ - _("%s%s[%s%s%s] %s%s%s invited by %s on %s"), + _("%s%s[%s%s%s] %s%s%s%s invited by %s on %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET, @@ -4070,17 +4105,20 @@ IRC_PROTOCOL_CALLBACK(346) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "invitelist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s invited by %s"), + _("%s%s[%s%s%s] %s%s%s%s invited by %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET, @@ -4089,17 +4127,20 @@ IRC_PROTOCOL_CALLBACK(346) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], NULL, 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "invitelist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s invited"), + _("%s%s[%s%s%s] %s%s%s%s invited"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET); @@ -4120,6 +4161,7 @@ IRC_PROTOCOL_CALLBACK(347) char *pos_args; struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; IRC_PROTOCOL_MIN_ARGS(4); @@ -4129,6 +4171,19 @@ IRC_PROTOCOL_CALLBACK(347) ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'I'); + if (ptr_modelist) + { + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + /* + * remove all items if no invite was received before + * the end of invite list + */ + irc_modelist_item_free_all (ptr_modelist); + } + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVED; + } weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "invitelist", ptr_buffer), @@ -4159,14 +4214,36 @@ IRC_PROTOCOL_CALLBACK(348) { struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; time_t datetime; const char *nick_address; + char str_number[64]; IRC_PROTOCOL_MIN_ARGS(5); ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'e'); + + if (ptr_modelist) + { + /* start receiving new list */ + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + irc_modelist_item_free_all (ptr_modelist); + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVING; + } + + sprintf (str_number, " %s[%s%d%s]", + IRC_COLOR_CHAT_DELIMITERS, + IRC_COLOR_RESET, + ((ptr_modelist->last_item) ? ptr_modelist->last_item->number + 1 : 0) + 1, + IRC_COLOR_CHAT_DELIMITERS); + } + else + str_number[0] = '\0'; + if (argc >= 6) { nick_address = irc_protocol_nick_address ( @@ -4175,18 +4252,21 @@ IRC_PROTOCOL_CALLBACK(348) if (argc >= 7) { datetime = (time_t)(atol (argv[6])); + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], datetime); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "exceptionlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), /* TRANSLATORS: "%s" after "on" is a date */ - _("%s%s[%s%s%s]%s exception %s%s%s by %s on %s"), + _("%s%s[%s%s%s]%s%s exception %s%s%s by %s on %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_RESET, IRC_COLOR_CHAT_HOST, argv[4], @@ -4196,17 +4276,20 @@ IRC_PROTOCOL_CALLBACK(348) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "exceptionlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s]%s exception %s%s%s by %s"), + _("%s%s[%s%s%s]%s%s exception %s%s%s by %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_RESET, IRC_COLOR_CHAT_HOST, argv[4], @@ -4216,17 +4299,20 @@ IRC_PROTOCOL_CALLBACK(348) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], NULL, 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "exceptionlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s]%s exception %s%s"), + _("%s%s[%s%s%s]%s%s exception %s%s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_RESET, IRC_COLOR_CHAT_HOST, argv[4]); @@ -4247,6 +4333,7 @@ IRC_PROTOCOL_CALLBACK(349) char *pos_args; struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; IRC_PROTOCOL_MIN_ARGS(4); @@ -4256,6 +4343,19 @@ IRC_PROTOCOL_CALLBACK(349) ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'e'); + if (ptr_modelist) + { + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + /* + * remove all items if no exception was received before + * the end of exception list + */ + irc_modelist_item_free_all (ptr_modelist); + } + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVED; + } weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "exceptionlist", ptr_buffer), @@ -4612,22 +4712,8 @@ IRC_PROTOCOL_CALLBACK(354) /* update away flag in nick */ if (ptr_channel && ptr_nick) { - if (pos_attr - && (weechat_hashtable_has_key (server->cap_list, "away-notify") - || ((IRC_SERVER_OPTION_INTEGER( - server, IRC_SERVER_OPTION_AWAY_CHECK) > 0) - && ((IRC_SERVER_OPTION_INTEGER( - server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS) == 0) - || (ptr_channel->nicks_count <= IRC_SERVER_OPTION_INTEGER( - server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS)))))) - { - irc_nick_set_away (server, ptr_channel, ptr_nick, - (pos_attr[0] == 'G') ? 1 : 0); - } - else - { - irc_nick_set_away (server, ptr_channel, ptr_nick, 0); - } + irc_nick_set_away (server, ptr_channel, ptr_nick, + (pos_attr && (pos_attr[0] == 'G')) ? 1 : 0); } /* update account flag in nick */ @@ -4659,7 +4745,7 @@ IRC_PROTOCOL_CALLBACK(354) date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), "%s%s[%s%s%s] %s%s %s%s%s%s%s%s(%s%s@%s%s)%s %s%s%s%s(%s)", - weechat_prefix("network"), + weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], @@ -4918,14 +5004,35 @@ IRC_PROTOCOL_CALLBACK(367) { struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; time_t datetime; const char *nick_address; + char str_number[64]; IRC_PROTOCOL_MIN_ARGS(5); ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'b'); + + if (ptr_modelist) + { + /* start receiving new list */ + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + irc_modelist_item_free_all (ptr_modelist); + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVING; + } + + sprintf (str_number, "%s[%s%d%s] ", + IRC_COLOR_CHAT_DELIMITERS, + IRC_COLOR_RESET, + ((ptr_modelist->last_item) ? ptr_modelist->last_item->number + 1 : 0) + 1, + IRC_COLOR_CHAT_DELIMITERS); + } + else + str_number[0] = '\0'; if (argc >= 6) { @@ -4935,18 +5042,21 @@ IRC_PROTOCOL_CALLBACK(367) if (argc >= 7) { datetime = (time_t)(atol (argv[6])); + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], datetime); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "banlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), /* TRANSLATORS: "%s" after "on" is a date */ - _("%s%s[%s%s%s] %s%s%s banned by %s on %s"), + _("%s%s[%s%s%s] %s%s%s%s banned by %s on %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET, @@ -4955,17 +5065,20 @@ IRC_PROTOCOL_CALLBACK(367) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], argv[5], 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "banlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s banned by %s"), + _("%s%s[%s%s%s] %s%s%s%s banned by %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET, @@ -4974,17 +5087,20 @@ IRC_PROTOCOL_CALLBACK(367) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[4], NULL, 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "banlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s banned"), + _("%s%s[%s%s%s] %s%s%s%s banned"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[4], IRC_COLOR_RESET); @@ -5005,6 +5121,7 @@ IRC_PROTOCOL_CALLBACK(368) char *pos_args; struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; IRC_PROTOCOL_MIN_ARGS(4); @@ -5014,6 +5131,19 @@ IRC_PROTOCOL_CALLBACK(368) ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, 'b'); + if (ptr_modelist) + { + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + /* + * remove all items if no ban was received before + * the end of ban list + */ + irc_modelist_item_free_all (ptr_modelist); + } + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVED; + } weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "banlist", ptr_buffer), @@ -5345,14 +5475,35 @@ IRC_PROTOCOL_CALLBACK(728) { struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; time_t datetime; const char *nick_address; + char str_number[64]; IRC_PROTOCOL_MIN_ARGS(6); ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, argv[4][0]); + + if (ptr_modelist) + { + /* start receiving new list */ + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + irc_modelist_item_free_all (ptr_modelist); + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVING; + } + + sprintf (str_number, "%s[%s%d%s] ", + IRC_COLOR_CHAT_DELIMITERS, + IRC_COLOR_RESET, + ((ptr_modelist->last_item) ? ptr_modelist->last_item->number + 1 : 0) + 1, + IRC_COLOR_CHAT_DELIMITERS); + } + else + str_number[0] = '\0'; if (argc >= 7) { @@ -5362,18 +5513,21 @@ IRC_PROTOCOL_CALLBACK(728) if (argc >= 8) { datetime = (time_t)(atol (argv[7])); + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[5], argv[6], datetime); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "quietlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), /* TRANSLATORS: "%s" after "on" is a date */ - _("%s%s[%s%s%s] %s%s%s quieted by %s on %s"), + _("%s%s[%s%s%s] %s%s%s%s quieted by %s on %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[5], IRC_COLOR_RESET, @@ -5382,17 +5536,20 @@ IRC_PROTOCOL_CALLBACK(728) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[5], argv[6], 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "quietlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s quieted by %s"), + _("%s%s[%s%s%s] %s%s%s%s quieted by %s"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[5], IRC_COLOR_RESET, @@ -5401,17 +5558,20 @@ IRC_PROTOCOL_CALLBACK(728) } else { + if (ptr_modelist) + irc_modelist_item_new (ptr_modelist, argv[5], NULL, 0); weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "quietlist", ptr_buffer), date, irc_protocol_tags (command, "irc_numeric", NULL, NULL), - _("%s%s[%s%s%s] %s%s%s quieted"), + _("%s%s[%s%s%s] %s%s%s%s quieted"), weechat_prefix ("network"), IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT_CHANNEL, argv[3], IRC_COLOR_CHAT_DELIMITERS, + str_number, IRC_COLOR_CHAT_HOST, argv[5], IRC_COLOR_RESET); @@ -5432,6 +5592,7 @@ IRC_PROTOCOL_CALLBACK(729) char *pos_args; struct t_irc_channel *ptr_channel; struct t_gui_buffer *ptr_buffer; + struct t_irc_modelist *ptr_modelist; IRC_PROTOCOL_MIN_ARGS(5); @@ -5441,6 +5602,19 @@ IRC_PROTOCOL_CALLBACK(729) ptr_channel = irc_channel_search (server, argv[3]); ptr_buffer = (ptr_channel && ptr_channel->nicks) ? ptr_channel->buffer : server->buffer; + ptr_modelist = irc_modelist_search (ptr_channel, argv[4][0]); + if (ptr_modelist) + { + if (ptr_modelist->state != IRC_MODELIST_STATE_RECEIVING) + { + /* + * remove all items if no quiet was received before + * the end of quiet list + */ + irc_modelist_item_free_all (ptr_modelist); + } + ptr_modelist->state = IRC_MODELIST_STATE_RECEIVED; + } weechat_printf_date_tags ( irc_msgbuffer_get_target_buffer ( server, NULL, command, "quietlist", ptr_buffer), @@ -5843,16 +6017,15 @@ irc_protocol_get_message_tag_time (struct t_hashtable *tags) void irc_protocol_recv_command (struct t_irc_server *server, const char *irc_message, - const char *msg_tags, const char *msg_command, const char *msg_channel) { int i, cmd_found, return_code, argc, decode_color, keep_trailing_spaces; int message_ignored; - char *dup_irc_message, *pos_space; + char *message_colors_decoded, *pos_space, *tags; struct t_irc_channel *ptr_channel; t_irc_recv_func *cmd_recv_func; - const char *cmd_name; + const char *cmd_name, *ptr_msg_after_tags; time_t date; const char *nick1, *address1, *host1; char *nick, *address, *address_color, *host, *host_no_color, *host_color; @@ -6014,29 +6187,48 @@ irc_protocol_recv_command (struct t_irc_server *server, if (!msg_command) return; - dup_irc_message = NULL; + message_colors_decoded = NULL; argv = NULL; argv_eol = NULL; hash_tags = NULL; date = 0; + ptr_msg_after_tags = irc_message; + /* get tags as hashtable */ - if (msg_tags) + if (irc_message && (irc_message[0] == '@')) { - hash_tags = irc_protocol_get_message_tags (msg_tags); - if (hash_tags) - date = irc_protocol_get_message_tag_time (hash_tags); + pos_space = strchr (irc_message, ' '); + if (pos_space) + { + tags = weechat_strndup (irc_message + 1, + pos_space - (irc_message + 1)); + if (tags) + { + hash_tags = irc_protocol_get_message_tags (tags); + if (hash_tags) + date = irc_protocol_get_message_tag_time (hash_tags); + free (tags); + } + ptr_msg_after_tags = pos_space; + while (ptr_msg_after_tags[0] == ' ') + { + ptr_msg_after_tags++; + } + } + else + ptr_msg_after_tags = NULL; } /* get nick/host/address from IRC message */ nick1 = NULL; address1 = NULL; host1 = NULL; - if (irc_message && (irc_message[0] == ':')) + if (ptr_msg_after_tags && (ptr_msg_after_tags[0] == ':')) { - nick1 = irc_message_get_nick_from_host (irc_message); - address1 = irc_message_get_address_from_host (irc_message); - host1 = irc_message + 1; + nick1 = irc_message_get_nick_from_host (ptr_msg_after_tags); + address1 = irc_message_get_address_from_host (ptr_msg_after_tags); + host1 = ptr_msg_after_tags + 1; } nick = (nick1) ? strdup (nick1) : NULL; address = (address1) ? strdup (address1) : NULL; @@ -6124,23 +6316,23 @@ irc_protocol_recv_command (struct t_irc_server *server, if (cmd_recv_func != NULL) { - if (irc_message) + if (ptr_msg_after_tags) { if (decode_color) { - dup_irc_message = irc_color_decode ( - irc_message, + message_colors_decoded = irc_color_decode ( + ptr_msg_after_tags, weechat_config_boolean (irc_config_network_colors_receive)); } else { - dup_irc_message = strdup (irc_message); + message_colors_decoded = strdup (ptr_msg_after_tags); } } else - dup_irc_message = NULL; - argv = weechat_string_split (dup_irc_message, " ", 0, 0, &argc); - argv_eol = weechat_string_split (dup_irc_message, " ", + message_colors_decoded = NULL; + argv = weechat_string_split (message_colors_decoded, " ", 0, 0, &argc); + argv_eol = weechat_string_split (message_colors_decoded, " ", 1 + keep_trailing_spaces, 0, NULL); return_code = (int) (cmd_recv_func) (server, @@ -6186,8 +6378,8 @@ end: free (host_no_color); if (host_color) free (host_color); - if (dup_irc_message) - free (dup_irc_message); + if (message_colors_decoded) + free (message_colors_decoded); if (argv) weechat_string_free_split (argv); if (argv_eol) diff --git a/src/plugins/irc/irc-protocol.h b/src/plugins/irc/irc-protocol.h index a890fd866..e45b6977b 100644 --- a/src/plugins/irc/irc-protocol.h +++ b/src/plugins/irc/irc-protocol.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_PROTOCOL_H -#define WEECHAT_IRC_PROTOCOL_H 1 +#ifndef WEECHAT_PLUGIN_IRC_PROTOCOL_H +#define WEECHAT_PLUGIN_IRC_PROTOCOL_H #include <time.h> @@ -87,8 +87,7 @@ extern const char *irc_protocol_tags (const char *command, const char *tags, const char *nick, const char *address); extern void irc_protocol_recv_command (struct t_irc_server *server, const char *irc_message, - const char *msg_tags, const char *msg_command, const char *msg_channel); -#endif /* WEECHAT_IRC_PROTOCOL_H */ +#endif /* WEECHAT_PLUGIN_IRC_PROTOCOL_H */ diff --git a/src/plugins/irc/irc-raw.c b/src/plugins/irc/irc-raw.c index d669aed10..ace1de3d8 100644 --- a/src/plugins/irc/irc-raw.c +++ b/src/plugins/irc/irc-raw.c @@ -1,7 +1,7 @@ /* * irc-raw.c - functions for IRC raw data messages * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * diff --git a/src/plugins/irc/irc-raw.h b/src/plugins/irc/irc-raw.h index d0601a10c..3ac0b04ad 100644 --- a/src/plugins/irc/irc-raw.h +++ b/src/plugins/irc/irc-raw.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_RAW_H -#define WEECHAT_IRC_RAW_H 1 +#ifndef WEECHAT_PLUGIN_IRC_RAW_H +#define WEECHAT_PLUGIN_IRC_RAW_H #include <time.h> @@ -61,4 +61,4 @@ 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); -#endif /* WEECHAT_IRC_RAW_H */ +#endif /* WEECHAT_PLUGIN_IRC_RAW_H */ diff --git a/src/plugins/irc/irc-redirect.c b/src/plugins/irc/irc-redirect.c index 44648a00d..64fc30ac6 100644 --- a/src/plugins/irc/irc-redirect.c +++ b/src/plugins/irc/irc-redirect.c @@ -1,7 +1,7 @@ /* * irc-redirect.c - redirection of IRC command output * - * Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2010-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -686,7 +686,7 @@ irc_redirect_message_add (struct t_irc_redirect *redirect, const char *message, /* add message to output */ if (redirect->output) { - redirect->output_size += strlen("\n") + strlen (message); + redirect->output_size += strlen ("\n") + strlen (message); output2 = realloc (redirect->output, redirect->output_size); if (!output2) { @@ -1209,7 +1209,7 @@ irc_redirect_print_log (struct t_irc_server *server) weechat_log_printf (" timeout . . . . . . : %d", ptr_redirect->timeout); weechat_log_printf (" command . . . . . . : '%s'", ptr_redirect->command); weechat_log_printf (" assigned_to_command : %d", ptr_redirect->assigned_to_command); - weechat_log_printf (" start_time. . . . . : %ld", ptr_redirect->start_time); + weechat_log_printf (" start_time. . . . . : %lld", (long long)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")); diff --git a/src/plugins/irc/irc-redirect.h b/src/plugins/irc/irc-redirect.h index 3d3e09f9e..f94e6ad07 100644 --- a/src/plugins/irc/irc-redirect.h +++ b/src/plugins/irc/irc-redirect.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2010-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_REDIRECT_H -#define WEECHAT_IRC_REDIRECT_H 1 +#ifndef WEECHAT_PLUGIN_IRC_REDIRECT_H +#define WEECHAT_PLUGIN_IRC_REDIRECT_H #include <time.h> @@ -132,4 +132,4 @@ extern int irc_redirect_command_hsignal_cb (const void *pointer, void *data, extern void irc_redirect_init (); extern void irc_redirect_end (); -#endif /* WEECHAT_IRC_REDIRECT_H */ +#endif /* WEECHAT_PLUGIN_IRC_REDIRECT_H */ diff --git a/src/plugins/irc/irc-sasl.c b/src/plugins/irc/irc-sasl.c index f397a656a..689e7ecb8 100644 --- a/src/plugins/irc/irc-sasl.c +++ b/src/plugins/irc/irc-sasl.c @@ -1,7 +1,7 @@ /* * irc-sasl.c - SASL authentication with IRC server * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -493,7 +493,7 @@ irc_sasl_mechanism_dh_blowfish (const char *data_base64, length_answer = 2 + length_key + length_username + length_password; answer = malloc (length_answer); ptr_answer = answer; - *((unsigned int *)ptr_answer) = htons(length_key); + *((unsigned int *)ptr_answer) = htons (length_key); ptr_answer += 2; memcpy (ptr_answer, public_bin, length_key); ptr_answer += length_key; @@ -554,7 +554,7 @@ irc_sasl_mechanism_dh_aes (const char *data_base64, secret_bin = NULL; public_bin = NULL; - if (irc_sasl_dh(data_base64, &public_bin, &secret_bin, &length_key) == 0) + if (irc_sasl_dh (data_base64, &public_bin, &secret_bin, &length_key) == 0) goto aesend; /* Select cipher algorithm: key length * 8 = cipher bit size */ @@ -596,7 +596,7 @@ irc_sasl_mechanism_dh_aes (const char *data_base64, goto aesend; if (gcry_cipher_setkey (gcrypt_handle, secret_bin, length_key) != 0) goto aesend; - if (gcry_cipher_setiv (gcrypt_handle, iv, sizeof(iv)) != 0) + if (gcry_cipher_setiv (gcrypt_handle, iv, sizeof (iv)) != 0) goto aesend; if (gcry_cipher_encrypt (gcrypt_handle, userpass_crypted, length_userpass, @@ -615,7 +615,7 @@ irc_sasl_mechanism_dh_aes (const char *data_base64, length_answer = 2 + length_key + sizeof (iv) + length_userpass; answer = malloc (length_answer); ptr_answer = answer; - *((unsigned int *)ptr_answer) = htons(length_key); + *((unsigned int *)ptr_answer) = htons (length_key); ptr_answer += 2; memcpy (ptr_answer, public_bin, length_key); ptr_answer += length_key; diff --git a/src/plugins/irc/irc-sasl.h b/src/plugins/irc/irc-sasl.h index 5c2eb1604..38a930fa6 100644 --- a/src/plugins/irc/irc-sasl.h +++ b/src/plugins/irc/irc-sasl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_SASL_H -#define WEECHAT_IRC_SASL_H 1 +#ifndef WEECHAT_PLUGIN_IRC_SASL_H +#define WEECHAT_PLUGIN_IRC_SASL_H struct t_irc_server; @@ -50,4 +50,4 @@ extern char *irc_sasl_mechanism_dh_aes (const char *data_base64, const char *sasl_username, const char *sasl_password); -#endif /* WEECHAT_IRC_SASL_H */ +#endif /* WEECHAT_PLUGIN_IRC_SASL_H */ diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index dd785c29a..2e43afab5 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -1,7 +1,7 @@ /* * irc-server.c - I/O communication with IRC servers * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2010 Emmanuel Bouthenot <kolter@openics.org> * Copyright (C) 2012 Simon Arlott * @@ -29,6 +29,7 @@ #include <stdio.h> #include <stdarg.h> #include <string.h> +#include <ctype.h> #include <time.h> #ifdef _WIN32 #include <winsock.h> @@ -117,6 +118,7 @@ char *irc_server_options[IRC_SERVER_NUM_OPTIONS][2] = { "msg_part", "WeeChat ${info:version}" }, { "msg_quit", "WeeChat ${info:version}" }, { "notify", "" }, + { "split_msg_max_length", "512" }, }; char *irc_server_casemapping_string[IRC_SERVER_NUM_CASEMAPPING] = @@ -337,6 +339,152 @@ irc_server_strncasecmp (struct t_irc_server *server, } /* + * Evaluates a string using the server as context: + * ${irc_server.xxx} and ${server} are replaced by a server option and the + * server name. + * + * Returns the evaluated string. + * + * Note: result must be freed after use. + */ + +char * +irc_server_eval_expression (struct t_irc_server *server, const char *string) +{ + struct t_hashtable *pointers, *extra_vars; + char *value; + + pointers = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + extra_vars = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + + if (server) + { + if (pointers) + weechat_hashtable_set (pointers, "irc_server", server); + if (extra_vars) + weechat_hashtable_set (extra_vars, "server", server->name); + } + + value = weechat_string_eval_expression (string, + pointers, extra_vars, NULL); + + if (pointers) + weechat_hashtable_free (pointers); + if (extra_vars) + weechat_hashtable_free (extra_vars); + + return value; +} + +/* + * Evaluates and returns the fingerprint. + * + * Returns the evaluated fingerprint, NULL if the fingerprint option is + * invalid. + * + * Note: result must be freed after use. + */ + +char * +irc_server_eval_fingerprint (struct t_irc_server *server) +{ +#ifdef HAVE_GNUTLS + const char *ptr_fingerprint; + char *fingerprint_eval, **fingerprints, *str_sizes; + int i, j, rc, algo, length; + + ptr_fingerprint = IRC_SERVER_OPTION_STRING(server, + IRC_SERVER_OPTION_SSL_FINGERPRINT); + + /* empty fingerprint is just ignored (considered OK) */ + if (!ptr_fingerprint || !ptr_fingerprint[0]) + return strdup (""); + + /* evaluate fingerprint */ + fingerprint_eval = irc_server_eval_expression (server, ptr_fingerprint); + if (!fingerprint_eval || !fingerprint_eval[0]) + { + weechat_printf ( + server->buffer, + _("%s%s: the evaluated fingerprint for server \"%s\" must not be " + "empty"), + weechat_prefix ("error"), + IRC_PLUGIN_NAME, + server->name); + if (fingerprint_eval) + free (fingerprint_eval); + return NULL; + } + + /* split fingerprint */ + fingerprints = weechat_string_split (fingerprint_eval, ",", 0, 0, NULL); + if (!fingerprints) + return fingerprint_eval; + + rc = 0; + for (i = 0; fingerprints[i]; i++) + { + length = strlen (fingerprints[i]); + algo = irc_server_fingerprint_search_algo_with_size (length * 4); + if (algo < 0) + { + rc = -1; + break; + } + for (j = 0; j < length; j++) + { + if (!isxdigit ((unsigned char)fingerprints[i][j])) + { + rc = -2; + break; + } + } + if (rc < 0) + break; + } + weechat_string_free_split (fingerprints); + switch (rc) + { + case -1: /* invalid size */ + str_sizes = irc_server_fingerprint_str_sizes (); + weechat_printf ( + server->buffer, + _("%s%s: invalid fingerprint size for server \"%s\", the " + "number of hexadecimal digits must be " + "one of: %s"), + weechat_prefix ("error"), + IRC_PLUGIN_NAME, + server->name, + (str_sizes) ? str_sizes : "?"); + if (str_sizes) + free (str_sizes); + free (fingerprint_eval); + return NULL; + case -2: /* invalid content */ + weechat_printf ( + server->buffer, + _("%s%s: invalid fingerprint for server \"%s\", it must " + "contain only hexadecimal digits (0-9, " + "a-f)"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, server->name); + free (fingerprint_eval); + return NULL; + } + return fingerprint_eval; +#else + return strdup (""); +#endif /* HAVE_GNUTLS */ +} + +/* * Checks if SASL is enabled on server. * * Returns: @@ -353,12 +501,12 @@ irc_server_sasl_enabled (struct t_irc_server *server) sasl_mechanism = IRC_SERVER_OPTION_INTEGER( server, IRC_SERVER_OPTION_SASL_MECHANISM); - sasl_username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME), - NULL, NULL, NULL); - sasl_password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD), - NULL, NULL, NULL); + sasl_username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME)); + sasl_password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD)); sasl_key = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_KEY); /* @@ -422,8 +570,7 @@ irc_server_set_addresses (struct t_irc_server *server, const char *addresses) if (addresses && addresses[0]) { - addresses_eval = weechat_string_eval_expression (addresses, - NULL, NULL, NULL); + addresses_eval = irc_server_eval_expression (server, addresses); if (server->addresses_eval && (strcmp (server->addresses_eval, addresses_eval) == 0)) { @@ -550,7 +697,7 @@ irc_server_set_nicks (struct t_irc_server *server, const char *nicks) } /* evaluate value */ - nicks2 = weechat_string_eval_expression (nicks, NULL, NULL, NULL); + nicks2 = irc_server_eval_expression (server, nicks); /* set new nicks */ server->nicks_array = weechat_string_split ( @@ -2498,7 +2645,10 @@ irc_server_sendf (struct t_irc_server *server, int flags, const char *tags, (new_msg) ? new_msg : items[i], NULL); - /* split message if needed (max is 512 bytes including final "\r\n") */ + /* + * split message if needed (max is 512 bytes by default, + * including the final "\r\n") + */ hashtable = irc_message_split (server, (new_msg) ? new_msg : items[i]); if (hashtable) @@ -2707,8 +2857,8 @@ void irc_server_msgq_flush () { struct t_irc_message *next; - char *ptr_data, *new_msg, *new_msg2, *ptr_msg, *ptr_msg2, *ptr_msg3, *pos; - char *tags, *nick, *host, *command, *channel, *arguments; + char *ptr_data, *new_msg, *new_msg2, *ptr_msg, *ptr_msg2, *pos; + char *nick, *host, *command, *channel, *arguments; char *msg_decoded, *msg_decoded_without_color; char str_modifier[128], modifier_data[256]; int pos_channel, pos_text, pos_decode; @@ -2773,7 +2923,7 @@ irc_server_msgq_flush () } irc_message_parse (irc_recv_msgq->server, ptr_msg, - &tags, NULL, &nick, &host, + NULL, NULL, &nick, &host, &command, &channel, &arguments, NULL, NULL, NULL, &pos_channel, &pos_text); @@ -2860,25 +3010,9 @@ irc_server_msgq_flush () else { /* message not redirected, display it */ - ptr_msg3 = ptr_msg2; - if (ptr_msg3[0] == '@') - { - /* skip tags in message */ - ptr_msg3 = strchr (ptr_msg3, ' '); - if (ptr_msg3) - { - while (ptr_msg3[0] == ' ') - { - ptr_msg3++; - } - } - else - ptr_msg3 = ptr_msg2; - } irc_protocol_recv_command ( irc_recv_msgq->server, - ptr_msg3, - tags, + ptr_msg2, command, channel); } @@ -3508,15 +3642,15 @@ irc_server_login (struct t_irc_server *server) const char *capabilities; char *password, *username, *realname, *username2; - password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD), - NULL, NULL, NULL); - username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME), - NULL, NULL, NULL); - realname = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME), - NULL, NULL, NULL); + password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD)); + username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME)); + realname = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME)); capabilities = IRC_SERVER_OPTION_STRING( server, IRC_SERVER_OPTION_CAPABILITIES); @@ -4235,8 +4369,12 @@ irc_server_gnutls_callback (const void *pointer, void *data, /* get fingerprint option in server */ ptr_fingerprint = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SSL_FINGERPRINT); - fingerprint_eval = weechat_string_eval_expression (ptr_fingerprint, - NULL, NULL, NULL); + fingerprint_eval = irc_server_eval_fingerprint (server); + if (!fingerprint_eval) + { + rc = -1; + goto end; + } /* set match options */ fingerprint_match = (ptr_fingerprint && ptr_fingerprint[0]) ? 0 : 1; @@ -4969,9 +5107,9 @@ irc_server_autojoin_create_buffers (struct t_irc_server *server) return; /* evaluate server option "autojoin" */ - autojoin = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN), - NULL, NULL, NULL); + autojoin = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN)); /* extract channel names from autojoin option */ if (autojoin && autojoin[0]) @@ -5042,9 +5180,9 @@ irc_server_autojoin_channels (struct t_irc_server *server) else { /* auto-join when connecting to server for first time */ - autojoin = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN), - NULL, NULL, NULL); + autojoin = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN)); if (!server->disable_autojoin && autojoin && autojoin[0]) irc_command_join_server (server, autojoin, 0, 0); if (autojoin) @@ -6079,26 +6217,26 @@ irc_server_print_log () weechat_log_printf (" chantypes. . . . . . : '%s'", ptr_server->chantypes); weechat_log_printf (" chanmodes. . . . . . : '%s'", ptr_server->chanmodes); weechat_log_printf (" monitor. . . . . . . : %d", ptr_server->monitor); - weechat_log_printf (" monitor_time . . . . : %ld", ptr_server->monitor_time); + weechat_log_printf (" monitor_time . . . . : %lld", (long long)ptr_server->monitor_time); weechat_log_printf (" reconnect_delay. . . : %d", ptr_server->reconnect_delay); - weechat_log_printf (" reconnect_start. . . : %ld", ptr_server->reconnect_start); - weechat_log_printf (" command_time . . . . : %ld", ptr_server->command_time); + weechat_log_printf (" reconnect_start. . . : %lld", (long long)ptr_server->reconnect_start); + weechat_log_printf (" command_time . . . . : %lld", (long long)ptr_server->command_time); weechat_log_printf (" reconnect_join . . . : %d", ptr_server->reconnect_join); weechat_log_printf (" disable_autojoin . . : %d", ptr_server->disable_autojoin); weechat_log_printf (" is_away. . . . . . . : %d", ptr_server->is_away); weechat_log_printf (" away_message . . . . : '%s'", ptr_server->away_message); - weechat_log_printf (" away_time. . . . . . : %ld", ptr_server->away_time); + weechat_log_printf (" away_time. . . . . . : %lld", (long long)ptr_server->away_time); weechat_log_printf (" lag. . . . . . . . . : %d", ptr_server->lag); weechat_log_printf (" lag_displayed. . . . : %d", ptr_server->lag_displayed); weechat_log_printf (" lag_check_time . . . : tv_sec:%d, tv_usec:%d", ptr_server->lag_check_time.tv_sec, ptr_server->lag_check_time.tv_usec); - weechat_log_printf (" lag_next_check . . . : %ld", ptr_server->lag_next_check); - weechat_log_printf (" lag_last_refresh . . : %ld", ptr_server->lag_last_refresh); + weechat_log_printf (" lag_next_check . . . : %lld", (long long)ptr_server->lag_next_check); + weechat_log_printf (" lag_last_refresh . . : %lld", (long long)ptr_server->lag_last_refresh); weechat_log_printf (" cmd_list_regexp. . . : 0x%lx", ptr_server->cmd_list_regexp); - weechat_log_printf (" last_user_message. . : %ld", ptr_server->last_user_message); - weechat_log_printf (" last_away_check. . . : %ld", ptr_server->last_away_check); - weechat_log_printf (" last_data_purge. . . : %ld", ptr_server->last_data_purge); + weechat_log_printf (" last_user_message. . : %lld", (long long)ptr_server->last_user_message); + weechat_log_printf (" last_away_check. . . : %lld", (long long)ptr_server->last_away_check); + weechat_log_printf (" last_data_purge. . . : %lld", (long long)ptr_server->last_data_purge); for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++) { weechat_log_printf (" outqueue[%02d] . . . . : 0x%lx", i, ptr_server->outqueue[i]); diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index 74987e675..401f627bb 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2012 Simon Arlott * * This file is part of WeeChat, the extensible chat client. @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_SERVER_H -#define WEECHAT_IRC_SERVER_H 1 +#ifndef WEECHAT_PLUGIN_IRC_SERVER_H +#define WEECHAT_PLUGIN_IRC_SERVER_H #include <time.h> #include <sys/time.h> @@ -84,6 +84,7 @@ enum t_irc_server_option IRC_SERVER_OPTION_MSG_PART, /* default part message */ IRC_SERVER_OPTION_MSG_QUIT, /* default quit message */ IRC_SERVER_OPTION_NOTIFY, /* notify list */ + IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH, /* max length of messages */ /* number of server options */ IRC_SERVER_NUM_OPTIONS, }; @@ -283,6 +284,8 @@ extern int irc_server_strcasecmp (struct t_irc_server *server, extern int irc_server_strncasecmp (struct t_irc_server *server, const char *string1, const char *string2, int max); +extern char *irc_server_eval_expression (struct t_irc_server *server, + const char *string); extern int irc_server_sasl_enabled (struct t_irc_server *server); extern char *irc_server_get_name_without_port (const char *name); extern int irc_server_set_addresses (struct t_irc_server *server, @@ -381,4 +384,4 @@ extern int irc_server_add_to_infolist (struct t_infolist *infolist, struct t_irc_server *server); extern void irc_server_print_log (); -#endif /* WEECHAT_IRC_SERVER_H */ +#endif /* WEECHAT_PLUGIN_IRC_SERVER_H */ diff --git a/src/plugins/irc/irc-upgrade.c b/src/plugins/irc/irc-upgrade.c index 098132514..107981609 100644 --- a/src/plugins/irc/irc-upgrade.c +++ b/src/plugins/irc/irc-upgrade.c @@ -1,7 +1,7 @@ /* * irc-upgrade.c - save/restore IRC plugin data when upgrading WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -30,6 +30,7 @@ #include "irc-channel.h" #include "irc-config.h" #include "irc-input.h" +#include "irc-modelist.h" #include "irc-nick.h" #include "irc-notify.h" #include "irc-raw.h" @@ -39,6 +40,7 @@ struct t_irc_server *irc_upgrade_current_server = NULL; struct t_irc_channel *irc_upgrade_current_channel = NULL; +struct t_irc_modelist *irc_upgrade_current_modelist = NULL; /* @@ -59,6 +61,8 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file) struct t_irc_redirect *ptr_redirect; struct t_irc_redirect_pattern *ptr_redirect_pattern; struct t_irc_notify *ptr_notify; + struct t_irc_modelist *ptr_modelist; + struct t_irc_modelist_item *ptr_item; struct t_irc_raw_message *ptr_raw_message; int rc; @@ -120,6 +124,46 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file) if (!rc) return 0; } + + for (ptr_modelist = ptr_channel->modelists; ptr_modelist; + ptr_modelist = ptr_modelist->next_modelist) + { + /* save modelist */ + infolist = weechat_infolist_new (); + if (!infolist) + return 0; + if (!irc_modelist_add_to_infolist (infolist, ptr_modelist)) + { + weechat_infolist_free (infolist); + return 0; + } + rc = weechat_upgrade_write_object (upgrade_file, + IRC_UPGRADE_TYPE_MODELIST, + infolist); + weechat_infolist_free (infolist); + if (!rc) + return 0; + + for (ptr_item = ptr_modelist->items; ptr_item; + ptr_item = ptr_item->next_item) + { + /* save modelist item */ + infolist = weechat_infolist_new (); + if (!infolist) + return 0; + if (!irc_modelist_item_add_to_infolist (infolist, ptr_item)) + { + weechat_infolist_free (infolist); + return 0; + } + rc = weechat_upgrade_write_object (upgrade_file, + IRC_UPGRADE_TYPE_MODELIST_ITEM, + infolist); + weechat_infolist_free (infolist); + if (!rc) + return 0; + } + } } /* save server redirects */ @@ -304,6 +348,7 @@ irc_upgrade_read_cb (const void *pointer, void *data, struct t_irc_nick *ptr_nick; struct t_irc_redirect *ptr_redirect; struct t_irc_notify *ptr_notify; + struct t_irc_modelist_item *ptr_item; struct t_gui_buffer *ptr_buffer; /* make C compiler happy */ @@ -675,6 +720,33 @@ irc_upgrade_read_cb (const void *pointer, void *data, } } break; + case IRC_UPGRADE_TYPE_MODELIST: + if (irc_upgrade_current_server && irc_upgrade_current_channel) + { + /* modelists are already created by the channel */ + irc_upgrade_current_modelist = irc_modelist_search ( + irc_upgrade_current_channel, + weechat_infolist_string (infolist, "type")[0]); + if (irc_upgrade_current_modelist) + { + irc_upgrade_current_modelist->state = weechat_infolist_integer (infolist, "state"); + } + } + break; + case IRC_UPGRADE_TYPE_MODELIST_ITEM: + if (irc_upgrade_current_server && irc_upgrade_current_channel && irc_upgrade_current_modelist) + { + ptr_item = irc_modelist_item_new ( + irc_upgrade_current_modelist, + weechat_infolist_string (infolist, "mask"), + weechat_infolist_string (infolist, "setter"), + weechat_infolist_time (infolist, "datetime")); + if (ptr_item) + { + ptr_item->number = weechat_infolist_integer (infolist, "number"); + } + } + break; case IRC_UPGRADE_TYPE_REDIRECT: if (irc_upgrade_current_server) { diff --git a/src/plugins/irc/irc-upgrade.h b/src/plugins/irc/irc-upgrade.h index 5b8c32729..fa2a0734c 100644 --- a/src/plugins/irc/irc-upgrade.h +++ b/src/plugins/irc/irc-upgrade.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -17,8 +17,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_UPGRADE_H -#define WEECHAT_IRC_UPGRADE_H 1 +#ifndef WEECHAT_PLUGIN_IRC_UPGRADE_H +#define WEECHAT_PLUGIN_IRC_UPGRADE_H #define IRC_UPGRADE_FILENAME "irc" @@ -33,9 +33,11 @@ enum t_irc_upgrade_type IRC_UPGRADE_TYPE_REDIRECT_PATTERN, IRC_UPGRADE_TYPE_REDIRECT, IRC_UPGRADE_TYPE_NOTIFY, + IRC_UPGRADE_TYPE_MODELIST, + IRC_UPGRADE_TYPE_MODELIST_ITEM, }; extern int irc_upgrade_save (); extern int irc_upgrade_load (); -#endif /* WEECHAT_IRC_UPGRADE_H */ +#endif /* WEECHAT_PLUGIN_IRC_UPGRADE_H */ diff --git a/src/plugins/irc/irc.c b/src/plugins/irc/irc.c index 8a1531575..3163e74b0 100644 --- a/src/plugins/irc/irc.c +++ b/src/plugins/irc/irc.c @@ -1,7 +1,7 @@ /* * irc.c - IRC (Internet Relay Chat) plugin for WeeChat * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * * This file is part of WeeChat, the extensible chat client. * @@ -50,7 +50,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("IRC (Internet Relay Chat) protocol")); WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>"); WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); -WEECHAT_PLUGIN_PRIORITY(5000); +WEECHAT_PLUGIN_PRIORITY(6000); struct t_weechat_plugin *weechat_irc_plugin = NULL; diff --git a/src/plugins/irc/irc.h b/src/plugins/irc/irc.h index 63befef64..2d22aa583 100644 --- a/src/plugins/irc/irc.h +++ b/src/plugins/irc/irc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> * * This file is part of WeeChat, the extensible chat client. @@ -18,8 +18,8 @@ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WEECHAT_IRC_H -#define WEECHAT_IRC_H 1 +#ifndef WEECHAT_PLUGIN_IRC_H +#define WEECHAT_PLUGIN_IRC_H #define weechat_plugin weechat_irc_plugin #define IRC_PLUGIN_NAME "irc" @@ -28,4 +28,4 @@ extern struct t_weechat_plugin *weechat_irc_plugin; extern int irc_signal_upgrade_received; -#endif /* WEECHAT_IRC_H */ +#endif /* WEECHAT_PLUGIN_IRC_H */ |