From 3c95f6aae9826c10a50c4a0f12c16fca6038410c Mon Sep 17 00:00:00 2001 From: "Todd A. Pratt" Date: Mon, 2 Nov 2015 08:00:52 -0500 Subject: [PATCH 001/140] Make C-w and M-backspace work right. --- src/fe-text/gui-entry.c | 38 +++++++++++++++++++++++++++----------- src/fe-text/gui-entry.h | 4 +++- src/fe-text/gui-readline.c | 7 +++++-- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 17a7c507..b7d58019 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -555,16 +555,31 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer) return; if (update_cutbuffer) { - /* put erased text to cutbuffer */ - if (entry->cutbuffer_len < size) { - g_free(entry->cutbuffer); - entry->cutbuffer = g_new(unichar, size+1); - } + if (entry->cutbuffer_len && update_cutbuffer == CUTBUFFER_PREPEND) { + int cutbuffer_new_size = entry->cutbuffer_len + size; + unichar *tmpcutbuffer = entry->cutbuffer; + entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); - entry->cutbuffer_len = size; - entry->cutbuffer[size] = '\0'; - memcpy(entry->cutbuffer, entry->text + entry->pos - size, - size * sizeof(unichar)); + memcpy(entry->cutbuffer, entry->text + entry->pos - size, + size * sizeof(unichar)); + memcpy(entry->cutbuffer + size, tmpcutbuffer, + + entry->cutbuffer_len * sizeof(unichar)); + entry->cutbuffer_len = cutbuffer_new_size; + entry->cutbuffer[cutbuffer_new_size] = '\0'; + + g_free(tmpcutbuffer); + } else if (update_cutbuffer) { + /* put erased text to cutbuffer */ + if (entry->cutbuffer_len < size) { + g_free(entry->cutbuffer); + entry->cutbuffer = g_new(unichar, size+1); + } + entry->cutbuffer_len = size; + entry->cutbuffer[size] = '\0'; + memcpy(entry->cutbuffer, entry->text + entry->pos - size, + size * sizeof(unichar)); + } } if (entry->utf8) @@ -601,7 +616,7 @@ void gui_entry_erase_cell(GUI_ENTRY_REC *entry) gui_entry_draw(entry); } -void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space) +void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, int repeat) { int to; @@ -624,7 +639,8 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space) } if (to > 0) to++; - gui_entry_erase(entry, entry->pos-to, TRUE); + gui_entry_erase(entry, entry->pos-to, + repeat ? CUTBUFFER_PREPEND : TRUE); } void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space) diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h index 29d8dea2..006a1858 100644 --- a/src/fe-text/gui-entry.h +++ b/src/fe-text/gui-entry.h @@ -1,6 +1,8 @@ #ifndef __GUI_ENTRY_H #define __GUI_ENTRY_H +#define CUTBUFFER_PREPEND 42 + typedef struct { int text_len, text_alloc; /* as shorts, not chars */ unichar *text; @@ -43,7 +45,7 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry); void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer); void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer); void gui_entry_erase_cell(GUI_ENTRY_REC *entry); -void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space); +void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, int repeat); void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space); void gui_entry_transpose_chars(GUI_ENTRY_REC *entry); diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index ec61e317..4d645748 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -68,6 +68,8 @@ static int paste_timeout_id; static void sig_input(void); +static int key_repeated = FALSE; + void input_listen_init(int handle) { readtag = g_input_add_poll(handle, @@ -361,6 +363,7 @@ static void sig_gui_key_pressed(gpointer keyp) int ret; key = GPOINTER_TO_INT(keyp); + key_repeated = key == prev_key; if (redir != NULL && redir->flags & ENTRY_REDIRECT_FLAG_HOTKEY) { handle_key_redirect(key); @@ -596,7 +599,7 @@ static void key_backspace(void) static void key_delete_previous_word(void) { - gui_entry_erase_word(active_entry, FALSE); + gui_entry_erase_word(active_entry, FALSE, key_repeated); } static void key_delete_next_word(void) @@ -606,7 +609,7 @@ static void key_delete_next_word(void) static void key_delete_to_previous_space(void) { - gui_entry_erase_word(active_entry, TRUE); + gui_entry_erase_word(active_entry, TRUE, key_repeated); } static void key_delete_to_next_space(void) From 1199ecc62f137eedb388b3dbd9b003cf1a8280f7 Mon Sep 17 00:00:00 2001 From: "Todd A. Pratt" Date: Fri, 13 Nov 2015 13:42:28 -0500 Subject: [PATCH 002/140] a facility for prepending or replacing the cutbuffer --- src/fe-text/gui-entry.c | 47 +++++++++++++++++++++----------------- src/fe-text/gui-entry.h | 13 ++++++++--- src/fe-text/gui-readline.c | 12 +++++----- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index a83bcf64..ec484cb5 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -534,7 +534,7 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry) return buf; } -void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer) +void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP update_cutbuffer) { int newpos, size = 0; @@ -545,7 +545,7 @@ void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer) gui_entry_erase(entry, size, update_cutbuffer); } -void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer) +void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_cutbuffer) { size_t w = 0; @@ -554,32 +554,39 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer) if (size == 0 || entry->pos < size) return; - if (update_cutbuffer) { - if (entry->cutbuffer_len && update_cutbuffer == CUTBUFFER_PREPEND) { - int cutbuffer_new_size = entry->cutbuffer_len + size; - unichar *tmpcutbuffer = entry->cutbuffer; - entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); + switch (update_cutbuffer) { + case CUTBUFFER_UPDATE_PREPEND: + if (entry->cutbuffer_len) { + int cutbuffer_new_size = entry->cutbuffer_len + size; + unichar *tmpcutbuffer = entry->cutbuffer; + entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); - memcpy(entry->cutbuffer, entry->text + entry->pos - size, - size * sizeof(unichar)); - memcpy(entry->cutbuffer + size, tmpcutbuffer, + memcpy(entry->cutbuffer, entry->text + entry->pos - size, + size * sizeof(unichar)); + memcpy(entry->cutbuffer + size, tmpcutbuffer, - entry->cutbuffer_len * sizeof(unichar)); - entry->cutbuffer_len = cutbuffer_new_size; - entry->cutbuffer[cutbuffer_new_size] = '\0'; + entry->cutbuffer_len * sizeof(unichar)); + entry->cutbuffer_len = cutbuffer_new_size; + entry->cutbuffer[cutbuffer_new_size] = '\0'; - g_free(tmpcutbuffer); - } else if (update_cutbuffer) { + g_free(tmpcutbuffer); + break; + } + /* fall through to REPLACE if cutbuffer_len was 0 */ + case CUTBUFFER_UPDATE_REPLACE: /* put erased text to cutbuffer */ if (entry->cutbuffer_len < size) { g_free(entry->cutbuffer); entry->cutbuffer = g_new(unichar, size+1); } + entry->cutbuffer_len = size; entry->cutbuffer[size] = '\0'; memcpy(entry->cutbuffer, entry->text + entry->pos - size, - size * sizeof(unichar)); - } + size * sizeof(unichar)); + break; + case CUTBUFFER_UPDATE_NOOP: + break; } if (entry->utf8) @@ -616,7 +623,7 @@ void gui_entry_erase_cell(GUI_ENTRY_REC *entry) gui_entry_draw(entry); } -void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, int repeat) +void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_OP cutbuffer_op) { int to; @@ -639,8 +646,6 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, int repeat) } if (to > 0) to++; - gui_entry_erase(entry, entry->pos-to, - repeat ? CUTBUFFER_PREPEND : TRUE); } void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space) @@ -666,7 +671,7 @@ void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space) size = to-entry->pos; entry->pos = to; - gui_entry_erase(entry, size, TRUE); + gui_entry_erase(entry, size, CUTBUFFER_UPDATE_REPLACE); } void gui_entry_transpose_chars(GUI_ENTRY_REC *entry) diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h index 006a1858..0f86e431 100644 --- a/src/fe-text/gui-entry.h +++ b/src/fe-text/gui-entry.h @@ -22,6 +22,12 @@ typedef struct { unsigned int utf8:1; } GUI_ENTRY_REC; +typedef enum { + CUTBUFFER_UPDATE_NOOP, + CUTBUFFER_UPDATE_REPLACE, + CUTBUFFER_UPDATE_PREPEND +} CUTBUFFER_UPDATE_OP; + extern GUI_ENTRY_REC *active_entry; GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8); @@ -42,10 +48,10 @@ void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str); void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr); char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry); -void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer); -void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer); +void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP update_cutbuffer); +void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_cutbuffer); void gui_entry_erase_cell(GUI_ENTRY_REC *entry); -void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, int repeat); +void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_OP cutbuffer_op); void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space); void gui_entry_transpose_chars(GUI_ENTRY_REC *entry); @@ -62,4 +68,5 @@ void gui_entry_move_words(GUI_ENTRY_REC *entry, int count, int to_space); void gui_entry_redraw(GUI_ENTRY_REC *entry); + #endif diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index c21925db..47689b4d 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -530,7 +530,7 @@ static void key_forward_to_space(void) static void key_erase_line(void) { gui_entry_set_pos(active_entry, active_entry->text_len); - gui_entry_erase(active_entry, active_entry->text_len, TRUE); + gui_entry_erase(active_entry, active_entry->text_len, CUTBUFFER_UPDATE_REPLACE); } static void key_erase_to_beg_of_line(void) @@ -538,7 +538,7 @@ static void key_erase_to_beg_of_line(void) int pos; pos = gui_entry_get_pos(active_entry); - gui_entry_erase(active_entry, pos, TRUE); + gui_entry_erase(active_entry, pos, CUTBUFFER_UPDATE_REPLACE); } static void key_erase_to_end_of_line(void) @@ -547,7 +547,7 @@ static void key_erase_to_end_of_line(void) pos = gui_entry_get_pos(active_entry); gui_entry_set_pos(active_entry, active_entry->text_len); - gui_entry_erase(active_entry, active_entry->text_len - pos, TRUE); + gui_entry_erase(active_entry, active_entry->text_len - pos, CUTBUFFER_UPDATE_REPLACE); } static void key_yank_from_cutbuffer(void) @@ -594,12 +594,12 @@ static void key_delete_character(void) static void key_backspace(void) { - gui_entry_erase(active_entry, 1, FALSE); + gui_entry_erase(active_entry, 1, CUTBUFFER_UPDATE_NOOP); } static void key_delete_previous_word(void) { - gui_entry_erase_word(active_entry, FALSE, key_repeated); + gui_entry_erase_word(active_entry, FALSE, CUTBUFFER_UPDATE_REPLACE); } static void key_delete_next_word(void) @@ -609,7 +609,7 @@ static void key_delete_next_word(void) static void key_delete_to_previous_space(void) { - gui_entry_erase_word(active_entry, TRUE, key_repeated); + gui_entry_erase_word(active_entry, TRUE, CUTBUFFER_UPDATE_REPLACE); } static void key_delete_to_next_space(void) From 7768f3e52074715e9c83bcded8607500e4434468 Mon Sep 17 00:00:00 2001 From: "Todd A. Pratt" Date: Fri, 13 Nov 2015 13:51:56 -0500 Subject: [PATCH 003/140] remove cruft from previous implementation --- src/fe-text/gui-entry.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h index 0f86e431..498f95b9 100644 --- a/src/fe-text/gui-entry.h +++ b/src/fe-text/gui-entry.h @@ -1,8 +1,6 @@ #ifndef __GUI_ENTRY_H #define __GUI_ENTRY_H -#define CUTBUFFER_PREPEND 42 - typedef struct { int text_len, text_alloc; /* as shorts, not chars */ unichar *text; From f90e10c5d27ee7d8a6663a432238cf487e7d372f Mon Sep 17 00:00:00 2001 From: "Todd A. Pratt" Date: Fri, 13 Nov 2015 14:01:25 -0500 Subject: [PATCH 004/140] remove more cruft from previous implementation --- src/fe-text/gui-readline.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 47689b4d..0ca68d80 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -68,8 +68,6 @@ static int paste_timeout_id; static void sig_input(void); -static int key_repeated = FALSE; - void input_listen_init(int handle) { readtag = g_input_add_poll(handle, @@ -363,7 +361,6 @@ static void sig_gui_key_pressed(gpointer keyp) int ret; key = GPOINTER_TO_INT(keyp); - key_repeated = key == prev_key; if (redir != NULL && redir->flags & ENTRY_REDIRECT_FLAG_HOTKEY) { handle_key_redirect(key); From bb8c0bbf4caf87172255993ce8a86f91a8cd4208 Mon Sep 17 00:00:00 2001 From: "Todd A. Pratt" Date: Fri, 13 Nov 2015 20:33:57 -0500 Subject: [PATCH 005/140] fix indentation, undelete line not meant to be deleted. --- src/fe-text/gui-entry.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index ec484cb5..650995bd 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -564,8 +564,8 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_ memcpy(entry->cutbuffer, entry->text + entry->pos - size, size * sizeof(unichar)); memcpy(entry->cutbuffer + size, tmpcutbuffer, + entry->cutbuffer_len * sizeof(unichar)); - entry->cutbuffer_len * sizeof(unichar)); entry->cutbuffer_len = cutbuffer_new_size; entry->cutbuffer[cutbuffer_new_size] = '\0'; @@ -646,6 +646,7 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_O } if (to > 0) to++; + gui_entry_erase(entry, entry->pos-to, TRUE); } void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space) From 15dfb27f80922f6f3b751da9e1395994c3026a62 Mon Sep 17 00:00:00 2001 From: "Todd A. Pratt" Date: Sat, 14 Nov 2015 09:07:35 -0500 Subject: [PATCH 006/140] use the enum name which was the original intended change --- src/fe-text/gui-entry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 650995bd..176ee431 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -646,7 +646,7 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_O } if (to > 0) to++; - gui_entry_erase(entry, entry->pos-to, TRUE); + gui_entry_erase(entry, entry->pos-to, CUTBUFFER_UPDATE_REPLACE); } void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space) From 25020808710f359e75a85a5252bf0f72443d09ee Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 14 Jan 2016 23:54:42 +0100 Subject: [PATCH 007/140] Change when the autocmds are sent. As per #175 if a -botcmd is specified for a given channel without a -bots parameter then the command is sent right after joining the channel. --- src/core/channels.c | 15 ++++++++++++--- src/irc/core/irc-channels-setup.c | 2 ++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/core/channels.c b/src/core/channels.c index 9af8b844..bfde605e 100644 --- a/src/core/channels.c +++ b/src/core/channels.c @@ -245,9 +245,18 @@ void channel_send_autocommands(CHANNEL_REC *channel) if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd) return; - if (rec->botmasks == NULL || !*rec->botmasks) { - /* just send the command. */ - eval_special_string(rec->autosendcmd, "", channel->server, channel); + if (channel->wholist == FALSE) { + /* if the autosendcmd alone (with no -bots parameter) has been + * specified then send it right after joining the channel, when + * the WHO list hasn't been yet retrieved. + * Depending on the value of the 'channel_max_who_sync' option + * the WHO list might not be retrieved after the join event. */ + + if (rec->botmasks == NULL || !*rec->botmasks) { + /* just send the command. */ + eval_special_string(rec->autosendcmd, "", channel->server, channel); + } + return; } diff --git a/src/irc/core/irc-channels-setup.c b/src/irc/core/irc-channels-setup.c index 2320352d..be69ad63 100644 --- a/src/irc/core/irc-channels-setup.c +++ b/src/irc/core/irc-channels-setup.c @@ -25,9 +25,11 @@ void irc_channels_setup_init(void) { signal_add("channel wholist", (SIGNAL_FUNC) channel_send_autocommands); + signal_add("channel joined", (SIGNAL_FUNC) channel_send_autocommands); } void irc_channels_setup_deinit(void) { signal_remove("channel wholist", (SIGNAL_FUNC) channel_send_autocommands); + signal_remove("channel joined", (SIGNAL_FUNC) channel_send_autocommands); } From 4af3a4731ee21f063b90fdb051efa90f6788d99f Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 12 Jan 2016 23:38:50 +0100 Subject: [PATCH 008/140] continue head --- INSTALL | 3 ++- NEWS | 2 +- configure.ac | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/INSTALL b/INSTALL index a83a6c76..234c6cf6 100644 --- a/INSTALL +++ b/INSTALL @@ -11,7 +11,8 @@ To compile irssi you need: For most people, this should work just fine: - ./configure + ./autogen.sh (for people who just cloned the repository) + ./configure (if this script already exists, skip ./autogen.sh) make su make install (not _really_ required except for perl support) diff --git a/NEWS b/NEWS index 405e8b4c..f44fdb56 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -v0.8.18-beta2 2016-01-13 The Irssi team +v0.8.18-head 2016-xx-xx The Irssi team * Modules will now require to define a void MODULENAME ## _abicheck(int *version) method to ensure that they are compiled against the correct Irssi diff --git a/configure.ac b/configure.ac index bf39c95f..c0efd5e3 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(irssi, 0.8.18-beta2) +AC_INIT(irssi, 0.8.18-head) AC_CONFIG_SRCDIR([src]) AC_CONFIG_AUX_DIR(build-aux) AC_PREREQ(2.50) From eba160ca6df194913d80df67c19e929b9428d77e Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 24 Jan 2016 23:02:40 +0100 Subject: [PATCH 009/140] Duplicate the code paths for autocommands. --- src/core/channels.c | 40 +++++++++++++++++++++---------- src/core/channels.h | 1 + src/irc/core/irc-channels-setup.c | 4 ++-- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/core/channels.c b/src/core/channels.c index bfde605e..9c3b92ba 100644 --- a/src/core/channels.c +++ b/src/core/channels.c @@ -231,6 +231,31 @@ static int match_nick_flags(SERVER_REC *server, NICK_REC *nick, char flag) /* Send the auto send command to channel */ void channel_send_autocommands(CHANNEL_REC *channel) +{ + CHANNEL_SETUP_REC *rec; + + g_return_if_fail(IS_CHANNEL(channel)); + + if (channel->session_rejoin) + return; + + rec = channel_setup_find(channel->name, channel->server->connrec->chatnet); + if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd) + return; + + /* if the autosendcmd alone (with no -bots parameter) has been + * specified then send it right after joining the channel, when + * the WHO list hasn't been yet retrieved. + * Depending on the value of the 'channel_max_who_sync' option + * the WHO list might not be retrieved after the join event. */ + + if (rec->botmasks == NULL || !*rec->botmasks) { + /* just send the command. */ + eval_special_string(rec->autosendcmd, "", channel->server, channel); + } +} + +void channel_send_botcommands(CHANNEL_REC *channel) { CHANNEL_SETUP_REC *rec; NICK_REC *nick; @@ -245,20 +270,9 @@ void channel_send_autocommands(CHANNEL_REC *channel) if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd) return; - if (channel->wholist == FALSE) { - /* if the autosendcmd alone (with no -bots parameter) has been - * specified then send it right after joining the channel, when - * the WHO list hasn't been yet retrieved. - * Depending on the value of the 'channel_max_who_sync' option - * the WHO list might not be retrieved after the join event. */ - - if (rec->botmasks == NULL || !*rec->botmasks) { - /* just send the command. */ - eval_special_string(rec->autosendcmd, "", channel->server, channel); - } - + /* this case has already been handled by channel_send_autocommands */ + if (rec->botmasks == NULL || !*rec->botmasks) return; - } /* find first available bot.. */ bots = g_strsplit(rec->botmasks, " ", -1); diff --git a/src/core/channels.h b/src/core/channels.h index 0839d69b..bd136fe2 100644 --- a/src/core/channels.h +++ b/src/core/channels.h @@ -31,6 +31,7 @@ void channel_change_visible_name(CHANNEL_REC *channel, const char *name); /* Send the auto send command to channel */ void channel_send_autocommands(CHANNEL_REC *channel); +void channel_send_botcommands(CHANNEL_REC *channel); void channels_init(void); void channels_deinit(void); diff --git a/src/irc/core/irc-channels-setup.c b/src/irc/core/irc-channels-setup.c index be69ad63..bbbc095c 100644 --- a/src/irc/core/irc-channels-setup.c +++ b/src/irc/core/irc-channels-setup.c @@ -24,12 +24,12 @@ void irc_channels_setup_init(void) { - signal_add("channel wholist", (SIGNAL_FUNC) channel_send_autocommands); + signal_add("channel wholist", (SIGNAL_FUNC) channel_send_botcommands); signal_add("channel joined", (SIGNAL_FUNC) channel_send_autocommands); } void irc_channels_setup_deinit(void) { - signal_remove("channel wholist", (SIGNAL_FUNC) channel_send_autocommands); + signal_remove("channel wholist", (SIGNAL_FUNC) channel_send_botcommands); signal_remove("channel joined", (SIGNAL_FUNC) channel_send_autocommands); } From d964950e5ddf9b83c67326b3a45108de4e5a44f2 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 24 Jan 2016 23:53:31 +0100 Subject: [PATCH 010/140] Serialize the 'name' attribute of the CHANNEL_REC. This way the code doing the serialization in 'sig_layout_save_item' is now symmetric with the loading code loading the data in 'sig_layout_restore'. --- src/fe-common/core/windows-layout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fe-common/core/windows-layout.c b/src/fe-common/core/windows-layout.c index 8ebcc12d..ce6b9910 100644 --- a/src/fe-common/core/windows-layout.c +++ b/src/fe-common/core/windows-layout.c @@ -168,12 +168,12 @@ static void sig_layout_save_item(WINDOW_REC *window, WI_ITEM_REC *item, chat_protocol_find_id(item->chat_type); if (proto != NULL) iconfig_node_set_str(subnode, "chat_type", proto->name); - iconfig_node_set_str(subnode, "name", item->visible_name); + iconfig_node_set_str(subnode, "name", item->name); if (item->server != NULL) { iconfig_node_set_str(subnode, "tag", item->server->tag); if (IS_CHANNEL(item)) { - rec = window_bind_add(window, item->server->tag, item->visible_name); + rec = window_bind_add(window, item->server->tag, item->name); if (rec != NULL) rec->sticky = TRUE; } From b229138b2ef6efc4ab91504801e27e9922b766b4 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 26 Jan 2016 09:33:46 +0100 Subject: [PATCH 011/140] Update perl.txt Mention known Perl Bugs (#386) --- docs/perl.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/perl.txt b/docs/perl.txt index 9688341f..59f65462 100644 --- a/docs/perl.txt +++ b/docs/perl.txt @@ -1193,3 +1193,7 @@ Client->{} -------------------- * Calling die in 'script error' handler causes segfault (#101) * Storing and later using any Irssi object may result in use-after-free related crash + - Workaround: always acquire fresh objects +* Calling $dcc->close from the "dcc created" signal will cause unstable behaviour and crashes (#386) + - Workaround: use "dcc request" signal instead AND call + &Irssi::signal_continue(@_); as the first thing From 87c0827471763ad5c086d1377ed91980e4b6c8d1 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 27 Jan 2016 14:31:55 +0100 Subject: [PATCH 012/140] Delete the HAVE_IPV6 ifdef. Welcome to the future. --- src/core/network.c | 112 ++++----------------------------------------- src/core/network.h | 10 +--- 2 files changed, 10 insertions(+), 112 deletions(-) diff --git a/src/core/network.c b/src/core/network.c index 0751aa95..4d3997a1 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -30,17 +30,11 @@ union sockaddr_union { struct sockaddr sa; struct sockaddr_in sin; -#ifdef HAVE_IPV6 struct sockaddr_in6 sin6; -#endif }; -#ifdef HAVE_IPV6 -# define SIZEOF_SOCKADDR(so) ((so).sa.sa_family == AF_INET6 ? \ +#define SIZEOF_SOCKADDR(so) ((so).sa.sa_family == AF_INET6 ? \ sizeof(so.sin6) : sizeof(so.sin)) -#else -# define SIZEOF_SOCKADDR(so) (sizeof(so.sin)) -#endif GIOChannel *g_io_channel_new(int handle) { @@ -56,7 +50,7 @@ GIOChannel *g_io_channel_new(int handle) IPADDR ip4_any = { AF_INET, -#if defined(HAVE_IPV6) && defined(IN6ADDR_ANY_INIT) +#if defined(IN6ADDR_ANY_INIT) IN6ADDR_ANY_INIT #else { INADDR_ANY } @@ -68,10 +62,8 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2) if (ip1->family != ip2->family) return 0; -#ifdef HAVE_IPV6 if (ip1->family == AF_INET6) return memcmp(&ip1->ip, &ip2->ip, sizeof(ip1->ip)) == 0; -#endif return memcmp(&ip1->ip, &ip2->ip, 4) == 0; } @@ -80,22 +72,16 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2) static void sin_set_ip(union sockaddr_union *so, const IPADDR *ip) { if (ip == NULL) { -#ifdef HAVE_IPV6 so->sin6.sin6_family = AF_INET6; so->sin6.sin6_addr = in6addr_any; -#else - so->sin.sin_family = AF_INET; - so->sin.sin_addr.s_addr = INADDR_ANY; -#endif return; } so->sin.sin_family = ip->family; -#ifdef HAVE_IPV6 + if (ip->family == AF_INET6) memcpy(&so->sin6.sin6_addr, &ip->ip, sizeof(ip->ip)); else -#endif memcpy(&so->sin.sin_addr, &ip->ip, 4); } @@ -103,31 +89,25 @@ void sin_get_ip(const union sockaddr_union *so, IPADDR *ip) { ip->family = so->sin.sin_family; -#ifdef HAVE_IPV6 if (ip->family == AF_INET6) memcpy(&ip->ip, &so->sin6.sin6_addr, sizeof(ip->ip)); else -#endif memcpy(&ip->ip, &so->sin.sin_addr, 4); } static void sin_set_port(union sockaddr_union *so, int port) { -#ifdef HAVE_IPV6 if (so->sin.sin_family == AF_INET6) so->sin6.sin6_port = htons((unsigned short)port); else -#endif so->sin.sin_port = htons((unsigned short)port); } static int sin_get_port(union sockaddr_union *so) { -#ifdef HAVE_IPV6 - if (so->sin.sin_family == AF_INET6) - return ntohs(so->sin6.sin6_port); -#endif - return ntohs(so->sin.sin_port); + return ntohs((so->sin.sin_family == AF_INET6) ? + so->sin6.sin6_port : + so->sin.sin_port); } /* Connect to socket */ @@ -272,7 +252,7 @@ GIOChannel *net_listen(IPADDR *my_ip, int *port) /* create the socket */ handle = socket(so.sin.sin_family, SOCK_STREAM, 0); -#ifdef HAVE_IPV6 + if (handle == -1 && (errno == EINVAL || errno == EAFNOSUPPORT)) { /* IPv6 is not supported by OS */ so.sin.sin_family = AF_INET; @@ -280,7 +260,7 @@ GIOChannel *net_listen(IPADDR *my_ip, int *port) handle = socket(AF_INET, SOCK_STREAM, 0); } -#endif + if (handle == -1) return NULL; @@ -399,21 +379,15 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port) Returns 0 = ok, others = error code for net_gethosterror() */ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) { -#ifdef HAVE_IPV6 union sockaddr_union *so; struct addrinfo hints, *ai, *ailist; int ret, count_v4, count_v6, use_v4, use_v6; -#else - struct hostent *hp; - int count; -#endif g_return_val_if_fail(addr != NULL, -1); memset(ip4, 0, sizeof(IPADDR)); memset(ip6, 0, sizeof(IPADDR)); -#ifdef HAVE_IPV6 memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; @@ -454,44 +428,21 @@ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) } freeaddrinfo(ailist); return 0; -#else - hp = gethostbyname(addr); - if (hp == NULL) - return h_errno; - - /* count IPs */ - count = 0; - while (hp->h_addr_list[count] != NULL) - count++; - - if (count == 0) - return HOST_NOT_FOUND; /* shouldn't happen? */ - - /* if there are multiple addresses, return random one */ - ip4->family = AF_INET; - memcpy(&ip4->ip, hp->h_addr_list[rand() % count], 4); - - return 0; -#endif } /* Get name for host, *name should be g_free()'d unless it's NULL. Return values are the same as with net_gethostbyname() */ int net_gethostbyaddr(IPADDR *ip, char **name) { -#ifdef HAVE_IPV6 union sockaddr_union so; int host_error; char hostname[NI_MAXHOST]; -#else - struct hostent *hp; -#endif g_return_val_if_fail(ip != NULL, -1); g_return_val_if_fail(name != NULL, -1); *name = NULL; -#ifdef HAVE_IPV6 + memset(&so, 0, sizeof(so)); sin_set_ip(&so, ip); @@ -502,36 +453,15 @@ int net_gethostbyaddr(IPADDR *ip, char **name) return host_error; *name = g_strdup(hostname); -#else - if (ip->family != AF_INET) return -1; - hp = gethostbyaddr((const char *) &ip->ip, 4, AF_INET); - if (hp == NULL) return -1; - - *name = g_strdup(hp->h_name); -#endif return 0; } int net_ip2host(IPADDR *ip, char *host) { -#ifdef HAVE_IPV6 if (!inet_ntop(ip->family, &ip->ip, host, MAX_IP_LEN)) return -1; -#else - unsigned long ip4; - if (ip->family != AF_INET) { - strcpy(host, "0.0.0.0"); - } else { - ip4 = ntohl(ip->ip.s_addr); - g_snprintf(host, MAX_IP_LEN, "%lu.%lu.%lu.%lu", - (ip4 & 0xff000000UL) >> 24, - (ip4 & 0x00ff0000) >> 16, - (ip4 & 0x0000ff00) >> 8, - (ip4 & 0x000000ff)); - } -#endif return 0; } @@ -542,12 +472,8 @@ int net_host2ip(const char *host, IPADDR *ip) if (strchr(host, ':') != NULL) { /* IPv6 */ ip->family = AF_INET6; -#ifdef HAVE_IPV6 if (inet_pton(AF_INET6, host, &ip->ip) == 0) return -1; -#else - ip->ip.s_addr = 0; -#endif } else { /* IPv4 */ ip->family = AF_INET; @@ -582,40 +508,20 @@ int net_geterror(GIOChannel *handle) /* get error of net_gethostname() */ const char *net_gethosterror(int error) { -#ifdef HAVE_IPV6 g_return_val_if_fail(error != 0, NULL); return gai_strerror(error); -#else - switch (error) { - case HOST_NOT_FOUND: - return "Host not found"; - case NO_ADDRESS: - return "No IP address found for name"; - case NO_RECOVERY: - return "A non-recovable name server error occurred"; - case TRY_AGAIN: - return "A temporary error on an authoritative name server"; - } - - /* unknown error */ - return NULL; -#endif } /* return TRUE if host lookup failed because it didn't exist (ie. not some error with name server) */ int net_hosterror_notfound(int error) { -#ifdef HAVE_IPV6 #ifdef EAI_NODATA /* NODATA is deprecated */ return error != 1 && (error == EAI_NONAME || error == EAI_NODATA); #else return error != 1 && (error == EAI_NONAME); #endif -#else - return error == HOST_NOT_FOUND || error == NO_ADDRESS; -#endif } /* Get name of TCP service */ diff --git a/src/core/network.h b/src/core/network.h index 73ac8dee..fb627b4d 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -21,19 +21,11 @@ struct _IPADDR { unsigned short family; -#ifdef HAVE_IPV6 struct in6_addr ip; -#else - struct in_addr ip; -#endif }; /* maxmimum string length of IP address */ -#ifdef HAVE_IPV6 -# define MAX_IP_LEN INET6_ADDRSTRLEN -#else -# define MAX_IP_LEN 20 -#endif +#define MAX_IP_LEN INET6_ADDRSTRLEN #define IPADDR_IS_V6(ip) ((ip)->family != AF_INET) From 70c7949cfe2f07545e5eeb4291631916ab28d07f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 27 Jan 2016 14:42:50 +0100 Subject: [PATCH 013/140] Update the configure script and INSTALL. Now that HAVE_IPV6 is gone remove all the references from the buildscript and documentation. --- INSTALL | 4 ---- acconfig.h | 1 - configure.ac | 33 --------------------------------- 3 files changed, 38 deletions(-) diff --git a/INSTALL b/INSTALL index 234c6cf6..4b20c1ba 100644 --- a/INSTALL +++ b/INSTALL @@ -29,10 +29,6 @@ configure options Build the irssi proxy (see startup-HOWTO). - --disable-ipv6 - - Disable IPv6 support. - --disable-ssl Disable SSL support. diff --git a/acconfig.h b/acconfig.h index 9ace70d8..53e268d7 100644 --- a/acconfig.h +++ b/acconfig.h @@ -1,5 +1,4 @@ /* misc.. */ -#undef HAVE_IPV6 #undef HAVE_SOCKS_H #undef HAVE_STATIC_PERL #undef HAVE_GMODULE diff --git a/configure.ac b/configure.ac index c0efd5e3..1a579911 100644 --- a/configure.ac +++ b/configure.ac @@ -140,15 +140,6 @@ AC_ARG_WITH(perl, fi, want_perl=static) -AC_ARG_ENABLE(ipv6, -[ --disable-ipv6 Disable IPv6 support], - if test x$enableval = xno; then - want_ipv6=no - else - want_ipv6=yes - fi, - want_ipv6=yes) - AC_ARG_ENABLE(dane, [ --enable-dane Enable DANE support], if test x$enableval = xno ; then @@ -577,29 +568,6 @@ COMMON_LIBS="$FE_COMMON_LIBS $COMMON_NOUI_LIBS" AC_SUBST(COMMON_NOUI_LIBS) AC_SUBST(COMMON_LIBS) -dnl ** -dnl ** IPv6 support -dnl ** - -have_ipv6=no -if test "x$want_ipv6" = "xyes"; then - AC_MSG_CHECKING([for IPv6]) - AC_CACHE_VAL(irssi_cv_type_in6_addr, - [AC_TRY_COMPILE([ - #include - #include - #include - #include - #include ], - [struct in6_addr i = in6addr_any; return &i == &i;], - have_ipv6=yes, - )]) - if test $have_ipv6 = yes; then - AC_DEFINE(HAVE_IPV6) - fi - AC_MSG_RESULT($have_ipv6) -fi - have_dane=no if test "x$want_dane" = "xyes"; then AC_MSG_CHECKING([for DANE]) @@ -742,7 +710,6 @@ echo "Install prefix ................... : $prefix" echo -echo "Building with IPv6 support ....... : $have_ipv6" echo "Building with SSL support ........ : $have_openssl" if test "x$have_openssl" = "xno" -a "x$enable_ssl" = "xyes"; then if test -f /etc/debian_version; then From f31b2026b4732e57f88af14796ac0dea4b2d0131 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 27 Jan 2016 15:04:07 +0100 Subject: [PATCH 014/140] Minor style fix in net_ip2host. --- src/core/network.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/core/network.c b/src/core/network.c index 4d3997a1..28189661 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -459,10 +459,7 @@ int net_gethostbyaddr(IPADDR *ip, char **name) int net_ip2host(IPADDR *ip, char *host) { - if (!inet_ntop(ip->family, &ip->ip, host, MAX_IP_LEN)) - return -1; - - return 0; + return inet_ntop(ip->family, &ip->ip, host, MAX_IP_LEN) ? 0 : -1; } int net_host2ip(const char *host, IPADDR *ip) From 118eb0a68ce3250aa4528e6086b2bd0567e7638c Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 27 Jan 2016 15:54:29 +0100 Subject: [PATCH 015/140] Call getnameinfo with NI_NAMEREQD flag. This way net_gethostbyaddr will fail when the system is unable to resolve the address to a valid host name. Without this flag in case of failure the function would return the ip address instead of failing. --- src/core/network.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/network.c b/src/core/network.c index 28189661..8abc1ba1 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -447,8 +447,10 @@ int net_gethostbyaddr(IPADDR *ip, char **name) sin_set_ip(&so, ip); /* save error to host_error for later use */ - host_error = getnameinfo((struct sockaddr *) &so, sizeof(so), - hostname, sizeof(hostname), NULL, 0, 0); + host_error = getnameinfo((struct sockaddr *)&so, sizeof(so), + hostname, sizeof(hostname), + NULL, 0, + NI_NAMEREQD); if (host_error != 0) return host_error; From 0cc8276e896441a186a8080f127e35d60112d758 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 27 Jan 2016 16:16:27 +0100 Subject: [PATCH 016/140] Add AI_ADDRCONFIG to the getaddrinfo hints. A first step to untangle the ipv4 vs ipv6 mess. At the time of writing Linux, OpenBSD and FreeBSD all support the AI_ADDRCONFIG flag. --- src/core/network.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/network.c b/src/core/network.c index 28189661..d777bdcc 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -390,6 +390,7 @@ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG; /* save error to host_error for later use */ ret = getaddrinfo(addr, NULL, &hints, &ailist); From 7674fd5936de3190f1fd3bba3ef82370a2941064 Mon Sep 17 00:00:00 2001 From: dequis Date: Fri, 29 Jan 2016 10:40:18 -0300 Subject: [PATCH 017/140] completion: Fix crash when the complist provided by a script has nulls Can be reproduced with aspell_complete.pl 1.00 by setting an invalid dictionary with "/set spell_dict a" --- src/fe-common/core/completion.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index a4715d23..1e7833a4 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -217,6 +217,11 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i want_space = TRUE; signal_emit("complete word", 5, &complist, window, word, linestart, &want_space); last_want_space = want_space; + + if (complist != NULL) { + /* Remove all nulls (from the signal) before doing further processing */ + complist = g_list_remove_all(g_list_first(complist), NULL); + } } g_free(linestart); From 876609901a5476ab2764a8002b9c57d25dc34f20 Mon Sep 17 00:00:00 2001 From: "Todd A. Pratt" Date: Sat, 30 Jan 2016 09:34:46 -0500 Subject: [PATCH 018/140] add an append operation to cut buffer handling --- src/fe-text/gui-entry.c | 46 +++++++++++++++++++++++++++-------------- src/fe-text/gui-entry.h | 1 + 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 6e13ba4e..58743ac3 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -582,25 +582,40 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_ if (size == 0 || entry->pos < size) return; + if (entry->cutbuffer_len == 0) { + update_cutbuffer = CUTBUFFER_UPDATE_REPLACE; + } + int cutbuffer_new_size = entry->cutbuffer_len + size; + unichar *tmpcutbuffer = entry->cutbuffer; switch (update_cutbuffer) { + case CUTBUFFER_UPDATE_APPEND: + entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); + if (entry->cutbuffer) { + memcpy(entry->cutbuffer, tmpcutbuffer, + entry->cutbuffer_len * sizeof(unichar)); + memcpy(entry->cutbuffer + entry->cutbuffer_len * sizeof(unichar), + entry->text + entry->pos - size, size * sizeof(unichar)); + + entry->cutbuffer_len = cutbuffer_new_size; + entry->cutbuffer[cutbuffer_new_size] = '\0'; + g_free(tmpcutbuffer); + } + break; + case CUTBUFFER_UPDATE_PREPEND: - if (entry->cutbuffer_len) { - int cutbuffer_new_size = entry->cutbuffer_len + size; - unichar *tmpcutbuffer = entry->cutbuffer; - entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); + entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); + if (entry->cutbuffer) { + memcpy(entry->cutbuffer, entry->text + entry->pos - size, + size * sizeof(unichar)); + memcpy(entry->cutbuffer + size, tmpcutbuffer, + entry->cutbuffer_len * sizeof(unichar)); - memcpy(entry->cutbuffer, entry->text + entry->pos - size, - size * sizeof(unichar)); - memcpy(entry->cutbuffer + size, tmpcutbuffer, - entry->cutbuffer_len * sizeof(unichar)); + entry->cutbuffer_len = cutbuffer_new_size; + entry->cutbuffer[cutbuffer_new_size] = '\0'; + g_free(tmpcutbuffer); + } + break; - entry->cutbuffer_len = cutbuffer_new_size; - entry->cutbuffer[cutbuffer_new_size] = '\0'; - - g_free(tmpcutbuffer); - break; - } - /* fall through to REPLACE if cutbuffer_len was 0 */ case CUTBUFFER_UPDATE_REPLACE: /* put erased text to cutbuffer */ if (entry->cutbuffer_len < size) { @@ -613,6 +628,7 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_ memcpy(entry->cutbuffer, entry->text + entry->pos - size, size * sizeof(unichar)); break; + case CUTBUFFER_UPDATE_NOOP: break; } diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h index 498f95b9..d22a7fb8 100644 --- a/src/fe-text/gui-entry.h +++ b/src/fe-text/gui-entry.h @@ -23,6 +23,7 @@ typedef struct { typedef enum { CUTBUFFER_UPDATE_NOOP, CUTBUFFER_UPDATE_REPLACE, + CUTBUFFER_UPDATE_APPEND, CUTBUFFER_UPDATE_PREPEND } CUTBUFFER_UPDATE_OP; From 966d002b55eb0b49a04833e5a51b9ab265013eab Mon Sep 17 00:00:00 2001 From: "Todd A. Pratt" Date: Sat, 30 Jan 2016 11:32:08 -0500 Subject: [PATCH 019/140] remove memory allocation check, spaces to tabs --- src/fe-text/gui-entry.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 58743ac3..78b9166d 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -589,32 +589,28 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_ unichar *tmpcutbuffer = entry->cutbuffer; switch (update_cutbuffer) { case CUTBUFFER_UPDATE_APPEND: - entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); - if (entry->cutbuffer) { - memcpy(entry->cutbuffer, tmpcutbuffer, - entry->cutbuffer_len * sizeof(unichar)); - memcpy(entry->cutbuffer + entry->cutbuffer_len * sizeof(unichar), - entry->text + entry->pos - size, size * sizeof(unichar)); + entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); + memcpy(entry->cutbuffer, tmpcutbuffer, + entry->cutbuffer_len * sizeof(unichar)); + memcpy(entry->cutbuffer + entry->cutbuffer_len * sizeof(unichar), + entry->text + entry->pos - size, size * sizeof(unichar)); - entry->cutbuffer_len = cutbuffer_new_size; - entry->cutbuffer[cutbuffer_new_size] = '\0'; - g_free(tmpcutbuffer); - } - break; + entry->cutbuffer_len = cutbuffer_new_size; + entry->cutbuffer[cutbuffer_new_size] = '\0'; + g_free(tmpcutbuffer); + break; case CUTBUFFER_UPDATE_PREPEND: - entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); - if (entry->cutbuffer) { - memcpy(entry->cutbuffer, entry->text + entry->pos - size, - size * sizeof(unichar)); - memcpy(entry->cutbuffer + size, tmpcutbuffer, - entry->cutbuffer_len * sizeof(unichar)); + entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); + memcpy(entry->cutbuffer, entry->text + entry->pos - size, + size * sizeof(unichar)); + memcpy(entry->cutbuffer + size, tmpcutbuffer, + entry->cutbuffer_len * sizeof(unichar)); - entry->cutbuffer_len = cutbuffer_new_size; - entry->cutbuffer[cutbuffer_new_size] = '\0'; - g_free(tmpcutbuffer); - } - break; + entry->cutbuffer_len = cutbuffer_new_size; + entry->cutbuffer[cutbuffer_new_size] = '\0'; + g_free(tmpcutbuffer); + break; case CUTBUFFER_UPDATE_REPLACE: /* put erased text to cutbuffer */ From 8708d8da49d68057ee8f32e64415c7109d237bd7 Mon Sep 17 00:00:00 2001 From: Lauri Nurmi Date: Sun, 31 Jan 2016 20:49:59 +0200 Subject: [PATCH 020/140] Add .gitattributes to ensure all shell scripts have LF as eol-style. Some Git clients on Windows may use CRLF otherwise, which effectively prevents running such scripts. --- .gitattributes | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..e1ae7d9d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# On Windows, some Git clients may normalize all text files' line-endings to +# CRLF, which causes obscure errors when running shell scripts. +*.sh eol=lf From 8723c0fb339dcf58c164fbc741122f9c3657ddea Mon Sep 17 00:00:00 2001 From: "Todd A. Pratt" Date: Wed, 10 Feb 2016 09:47:10 -0500 Subject: [PATCH 021/140] fix whitespace --- src/fe-text/gui-entry.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 78b9166d..27778b2b 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -582,11 +582,11 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_ if (size == 0 || entry->pos < size) return; - if (entry->cutbuffer_len == 0) { - update_cutbuffer = CUTBUFFER_UPDATE_REPLACE; - } - int cutbuffer_new_size = entry->cutbuffer_len + size; - unichar *tmpcutbuffer = entry->cutbuffer; + if (entry->cutbuffer_len == 0) { + update_cutbuffer = CUTBUFFER_UPDATE_REPLACE; + } + int cutbuffer_new_size = entry->cutbuffer_len + size; + unichar *tmpcutbuffer = entry->cutbuffer; switch (update_cutbuffer) { case CUTBUFFER_UPDATE_APPEND: entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); @@ -621,8 +621,7 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_ entry->cutbuffer_len = size; entry->cutbuffer[size] = '\0'; - memcpy(entry->cutbuffer, entry->text + entry->pos - size, - size * sizeof(unichar)); + memcpy(entry->cutbuffer, entry->text + entry->pos - size, size * sizeof(unichar)); break; case CUTBUFFER_UPDATE_NOOP: From 88e2449f832d5c64b8ea30047f15319a66b17c1f Mon Sep 17 00:00:00 2001 From: Lukas Mai Date: Wed, 17 Feb 2016 22:34:44 +0100 Subject: [PATCH 022/140] fix formatting --- src/irc/proxy/listen.c | 70 +++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 5dc9a704..ad1e4588 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -48,7 +48,7 @@ static void remove_client(CLIENT_REC *rec) signal_emit("proxy client disconnected", 1, rec); printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE, - "Proxy: Client %s:%d disconnected", rec->host, rec->port); + "Proxy: Client %s:%d disconnected", rec->host, rec->port); g_free(rec->proxy_address); net_sendbuffer_destroy(rec->handle, TRUE); @@ -59,7 +59,7 @@ static void remove_client(CLIENT_REC *rec) } static void proxy_redirect_event(CLIENT_REC *client, const char *command, - int count, const char *arg, int remote) + int count, const char *arg, int remote) { char *str; @@ -67,7 +67,7 @@ static void proxy_redirect_event(CLIENT_REC *client, const char *command, str = g_strdup_printf("proxy %p", client); server_redirect_event(client->server, command, count, - arg, remote, NULL, "", str, NULL); + arg, remote, NULL, "", str, NULL); g_free(str); } @@ -94,15 +94,15 @@ static void grab_who(CLIENT_REC *client, const char *channel) } proxy_redirect_event(client, "who", - client->server->one_endofwho ? 1 : count, - arg->str, -1); + client->server->one_endofwho ? 1 : count, + arg->str, -1); g_strfreev(list); g_string_free(arg, TRUE); } static void handle_client_connect_cmd(CLIENT_REC *client, - const char *cmd, const char *args) + const char *cmd, const char *args) { const char *password; @@ -114,7 +114,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client, else { /* wrong password! */ remove_client(client); - return; + return; } } else if (g_strcmp0(cmd, "NICK") == 0) { g_free_not_null(client->nick); @@ -130,8 +130,8 @@ static void handle_client_connect_cmd(CLIENT_REC *client, } else { signal_emit("proxy client connected", 1, client); printtext(client->server, NULL, MSGLEVEL_CLIENTNOTICE, - "Proxy: Client %s:%d connected", - client->host, client->port); + "Proxy: Client %s:%d connected", + client->host, client->port); client->connected = TRUE; proxy_dump_data(client); } @@ -139,7 +139,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client, } static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, - const char *data) + const char *data) { GSList *tmp; if (!client->connected) { @@ -162,8 +162,8 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, g_ascii_strcasecmp(target, client->proxy_address) == 0 || g_ascii_strcasecmp(target, client->nick) == 0) { proxy_outdata(client, ":%s PONG %s :%s\r\n", - client->proxy_address, - client->proxy_address, origin); + client->proxy_address, + client->proxy_address, origin); g_free(params); return; } @@ -174,25 +174,25 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, if (g_ascii_strcasecmp(args, "CTCP ON") == 0) { /* client wants all ctcps */ client->want_ctcp = 1; - for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { + for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; - if ((g_ascii_strcasecmp(client->listen->ircnet,rec->listen->ircnet) == 0) && - /* kludgy way to check if the clients aren't the same */ - (client->recv_tag != rec->recv_tag)) { - if (rec->want_ctcp == 1) - proxy_outdata(rec, ":%s NOTICE %s :Another client is now receiving CTCPs sent to %s\r\n", - rec->proxy_address, rec->nick, rec->listen->ircnet); - rec->want_ctcp = 0; - } + if (g_ascii_strcasecmp(client->listen->ircnet, rec->listen->ircnet) == 0 && + /* kludgy way to check if the clients aren't the same */ + client->recv_tag != rec->recv_tag) { + if (rec->want_ctcp == 1) + proxy_outdata(rec, ":%s NOTICE %s :Another client is now receiving CTCPs sent to %s\r\n", + rec->proxy_address, rec->nick, rec->listen->ircnet); + rec->want_ctcp = 0; + } } proxy_outdata(client, ":%s NOTICE %s :You're now receiving CTCPs sent to %s\r\n", - client->proxy_address, client->nick,client->listen->ircnet); + client->proxy_address, client->nick, client->listen->ircnet); } else if (g_ascii_strcasecmp(args, "CTCP OFF") == 0) { - /* client wants proxy to handle all ctcps */ + /* client wants proxy to handle all ctcps */ client->want_ctcp = 0; proxy_outdata(client, ":%s NOTICE %s :Proxy is now handling itself CTCPs sent to %s\r\n", - client->proxy_address, client->nick, client->listen->ircnet); + client->proxy_address, client->nick, client->listen->ircnet); } else { signal_emit("proxy client command", 3, client, args, data); } @@ -201,11 +201,11 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, if (client->server == NULL || !client->server->connected) { proxy_outdata(client, ":%s NOTICE %s :Not connected to server\r\n", - client->proxy_address, client->nick); - return; + client->proxy_address, client->nick); + return; } - /* check if the command could be redirected */ + /* check if the command could be redirected */ if (g_strcmp0(cmd, "WHO") == 0) grab_who(client, args); else if (g_strcmp0(cmd, "WHOWAS") == 0) @@ -263,29 +263,29 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, char *params, *target, *msg; params = event_get_params(args, 2 | PARAM_FLAG_GETREST, - &target, &msg); + &target, &msg); proxy_outserver_all_except(client, "PRIVMSG %s", args); ignore_next = TRUE; if (*msg != '\001' || msg[strlen(msg)-1] != '\001') { signal_emit(server_ischannel(SERVER(client->server), target) ? - "message own_public" : "message own_private", 4, - client->server, msg, target, target); + "message own_public" : "message own_private", 4, + client->server, msg, target, target); } else if (strncmp(msg+1, "ACTION ", 7) == 0) { /* action */ - msg[strlen(msg)-1] = '\0'; + msg[strlen(msg)-1] = '\0'; signal_emit("message irc own_action", 3, - client->server, msg+8, target); + client->server, msg+8, target); } else { - /* CTCP */ + /* CTCP */ char *p; msg[strlen(msg)-1] = '\0'; p = strchr(msg, ' '); - if (p != NULL) *p++ = '\0'; else p = ""; + if (p != NULL) *p++ = '\0'; else p = ""; signal_emit("message irc own_ctcp", 4, - client->server, msg+1, p, target); + client->server, msg+1, p, target); } ignore_next = FALSE; g_free(params); From 4732e33ca9c9f9a48b57062ab254bf3aa90078bf Mon Sep 17 00:00:00 2001 From: Lukas Mai Date: Wed, 17 Feb 2016 23:06:51 +0100 Subject: [PATCH 023/140] irssi proxy: allow multiplexing multiple networks over a single port --- src/irc/proxy/listen.c | 58 +++++++++++++++++++++++++++++++++--------- src/irc/proxy/proxy.h | 1 + src/perl/irc/Irc.xs | 1 + 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index ad1e4588..2322d47a 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -108,14 +108,44 @@ static void handle_client_connect_cmd(CLIENT_REC *client, password = settings_get_str("irssiproxy_password"); - if (password != NULL && g_strcmp0(cmd, "PASS") == 0) { - if (g_strcmp0(password, args) == 0) - client->pass_sent = TRUE; - else { + if (g_strcmp0(cmd, "PASS") == 0) { + const char *args_pass; + + if (!client->multiplex) { + args_pass = args; + } else { + IRC_SERVER_REC *server; + char *tag; + const char *tag_end; + + if ((tag_end = strchr(args, ':'))) { + args_pass = tag_end + 1; + } else { + tag_end = args + strlen(args); + args_pass = ""; + } + + tag = g_strndup(args, tag_end - args); + server = IRC_SERVER(server_find_chatnet(tag)); + g_free(tag); + + if (!server) { + /* an invalid network was specified */ + remove_client(client); + return; + } + + client->server = server; + g_free(client->proxy_address); + client->proxy_address = g_strdup_printf("%*s.proxy", (int)(tag_end - args), args); + } + + if (password && g_strcmp0(password, args_pass) != 0) { /* wrong password! */ remove_client(client); return; } + client->pass_sent = TRUE; } else if (g_strcmp0(cmd, "NICK") == 0) { g_free_not_null(client->nick); client->nick = g_strdup(args); @@ -124,7 +154,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client, } if (client->nick != NULL && client->user_sent) { - if (*password != '\0' && !client->pass_sent) { + if ((*password != '\0' || client->multiplex) && !client->pass_sent) { /* client didn't send us PASS, kill it */ remove_client(client); } else { @@ -337,7 +367,7 @@ static void sig_listen(LISTEN_REC *listen) CLIENT_REC *rec; IPADDR ip; NET_SENDBUF_REC *sendbuf; - GIOChannel *handle; + GIOChannel *handle; char host[MAX_IP_LEN]; int port; @@ -352,9 +382,13 @@ static void sig_listen(LISTEN_REC *listen) rec = g_new0(CLIENT_REC, 1); rec->listen = listen; rec->handle = sendbuf; - rec->host = g_strdup(host); + rec->host = g_strdup(host); rec->port = port; - if (g_strcmp0(listen->ircnet, "*") == 0) { + if (g_strcmp0(listen->ircnet, "?") == 0) { + rec->multiplex = TRUE; + rec->proxy_address = g_strdup("multiplex.proxy"); + rec->server = NULL; + } else if (g_strcmp0(listen->ircnet, "*") == 0) { rec->proxy_address = g_strdup("irc.proxy"); rec->server = servers == NULL ? NULL : IRC_SERVER(servers->data); } else { @@ -363,15 +397,15 @@ static void sig_listen(LISTEN_REC *listen) IRC_SERVER(server_find_chatnet(listen->ircnet)); } rec->recv_tag = g_input_add(handle, G_INPUT_READ, - (GInputFunction) sig_listen_client, rec); + (GInputFunction) sig_listen_client, rec); proxy_clients = g_slist_prepend(proxy_clients, rec); - rec->listen->clients = g_slist_prepend(rec->listen->clients, rec); + listen->clients = g_slist_prepend(listen->clients, rec); signal_emit("proxy client connecting", 1, rec); printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE, - "Proxy: New client %s:%d on port %d (%s)", - rec->host, rec->port, listen->port, listen->ircnet); + "Proxy: New client %s:%d on port %d (%s)", + rec->host, rec->port, listen->port, listen->ircnet); } static void sig_incoming(IRC_SERVER_REC *server, const char *line) diff --git a/src/irc/proxy/proxy.h b/src/irc/proxy/proxy.h index 158b0675..f37e9c95 100644 --- a/src/irc/proxy/proxy.h +++ b/src/irc/proxy/proxy.h @@ -29,6 +29,7 @@ typedef struct { unsigned int user_sent:1; unsigned int connected:1; unsigned int want_ctcp:1; + unsigned int multiplex:1; } CLIENT_REC; #endif diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs index db5c5f79..4217b4eb 100644 --- a/src/perl/irc/Irc.xs +++ b/src/perl/irc/Irc.xs @@ -157,6 +157,7 @@ static void perl_client_fill_hash(HV *hv, CLIENT_REC *client) (void) hv_store(hv, "user_sent", 9, newSViv(client->user_sent), 0); (void) hv_store(hv, "connected", 9, newSViv(client->connected), 0); (void) hv_store(hv, "want_ctcp", 9, newSViv(client->want_ctcp), 0); + (void) hv_store(hv, "multiplex", 9, newSViv(client->multiplex), 0); (void) hv_store(hv, "ircnet", 6, new_pv(client->listen->ircnet), 0); } From effb00b858db17b3abf27661682255bd8139a95a Mon Sep 17 00:00:00 2001 From: Lukas Mai Date: Thu, 18 Feb 2016 01:17:24 +0100 Subject: [PATCH 024/140] add some documentation --- docs/proxy.txt | 12 ++++++++++++ docs/startup-HOWTO.html | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/docs/proxy.txt b/docs/proxy.txt index e6360a82..224d24e3 100644 --- a/docs/proxy.txt +++ b/docs/proxy.txt @@ -30,6 +30,18 @@ There we have 3 different irc networks answering in 3 ports. Note that you'll have to make the correct /IRCNET ADD and /SERVER ADD commands to make it work properly. +The special network name "?" allows the client to select the network +dynamically on connect: + + /SET irssiproxy_ports ?=2777 + +Now the client can send : as the server password, e.g. + + /CONNECT ... 2777 efnet:secret + +to connect to efnet. If there is no irssiproxy_password set, you can +omit the ":" and just send the network name as the password. + By default, the proxy binds to all available interfaces. To make it only listen on (for example) the loopback address: diff --git a/docs/startup-HOWTO.html b/docs/startup-HOWTO.html index deff3116..1b912b96 100644 --- a/docs/startup-HOWTO.html +++ b/docs/startup-HOWTO.html @@ -735,6 +735,13 @@ reason, and you only use one server connection, you may simply set:

/SET irssiproxy_ports *=2777 +

The special network name ? allows the client to select the +network dynamically on connect (see below):

+ +
+/SET irssiproxy_ports ?=2777
+
+

Usage in client side:

Just connect to the irssi proxy like it is a normal server with password @@ -745,6 +752,16 @@ specified in /SET irssiproxy_password. For example:

/SERVER ADD -network efnet my.irssi-proxy.org 2778 secret +

Or, if you used ? in irssiproxy_ports:

+ +
+/SERVER ADD -network IRCnet my.irssi-proxy.org 2777 IRCnet:secret
+/SERVER ADD -network efnet my.irssi-proxy.org 2777 efnet:secret
+
+ +

I.e. the network to connect to is specified as part of the password, +separated by : from the actual proxy password.

+

Irssi proxy works fine with other IRC clients as well.

SOCKS

From c9ce0c521a559727493b42f422b5cc10ede2d9b2 Mon Sep 17 00:00:00 2001 From: Lukas Mai Date: Thu, 18 Feb 2016 02:23:00 +0100 Subject: [PATCH 025/140] make pointer check explicit --- src/irc/proxy/listen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 2322d47a..cd946baa 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -118,7 +118,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client, char *tag; const char *tag_end; - if ((tag_end = strchr(args, ':'))) { + if ((tag_end = strchr(args, ':')) != NULL) { args_pass = tag_end + 1; } else { tag_end = args + strlen(args); From 3167ccfbc21e6918133e5898f5e76596bb6de788 Mon Sep 17 00:00:00 2001 From: Lukas Mai Date: Thu, 18 Feb 2016 02:23:09 +0100 Subject: [PATCH 026/140] remove redundant check --- src/irc/proxy/listen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index cd946baa..3ec83773 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -140,7 +140,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client, client->proxy_address = g_strdup_printf("%*s.proxy", (int)(tag_end - args), args); } - if (password && g_strcmp0(password, args_pass) != 0) { + if (g_strcmp0(password, args_pass) != 0) { /* wrong password! */ remove_client(client); return; From 9f0e5da208f9ee775b82d50ff959d8599d1e1151 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 24 Feb 2016 00:35:27 +0530 Subject: [PATCH 027/140] use a #define'd LINE_SPLIT_LIMIT instead of hardcoding 400 --- src/fe-text/gui-readline.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 0dd17394..51ccab5e 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -40,6 +40,9 @@ #include #include +/* After LINE_SPLIT_LIMIT characters, the message will be split into multiple lines */ +#define LINE_SPLIT_LIMIT 400 + typedef void (*ENTRY_REDIRECT_KEY_FUNC) (int key, void *data, SERVER_REC *server, WI_ITEM_REC *item); typedef void (*ENTRY_REDIRECT_ENTRY_FUNC) (const char *line, void *data, SERVER_REC *server, WI_ITEM_REC *item); @@ -227,7 +230,7 @@ static void paste_buffer_join_lines(GArray *buf) } /* all looks fine - now remove the whitespace, but don't let lines - get longer than 400 chars */ + get longer than LINE_SPLIT_LIMIT chars */ dest = arr; last_lf = TRUE; last_lf_pos = NULL; line_len = 0; for (i = 0; i < buf->len; i++) { if (last_lf && isblank(arr[i])) { @@ -245,7 +248,7 @@ static void paste_buffer_join_lines(GArray *buf) last_lf = TRUE; } else { last_lf = FALSE; - if (++line_len >= 400 && last_lf_pos != NULL) { + if (++line_len >= LINE_SPLIT_LIMIT && last_lf_pos != NULL) { memmove(last_lf_pos+1, last_lf_pos, (dest - last_lf_pos) * sizeof(unichar)); *last_lf_pos = '\n'; last_lf_pos = NULL; From ef0c7d3e7a6df6de1f8280ae8ae777a068d073c7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 24 Feb 2016 00:36:35 +0530 Subject: [PATCH 028/140] Make pasting warning appear when long pastes are going to be split into many lines --- src/fe-text/gui-readline.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 51ccab5e..ff91f9e3 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -360,11 +360,24 @@ static void insert_paste_prompt(void) { char *str; + /* The actual number of lines that will show up post-line-split */ + int actual_line_count = paste_line_count; + int split_lines = paste_buffer->len / LINE_SPLIT_LIMIT; + + /* in case this prompt is happening due to line-splitting, calculate the + number of lines obtained from this. The number isn't entirely accurate; + we just choose the greater of the two since the exact value isn't + important */ + if (split_lines > paste_verify_line_count && + split_lines > paste_line_count) { + actual_line_count = split_lines; + } + paste_prompt = TRUE; paste_old_prompt = g_strdup(active_entry->prompt); printformat_window(active_win, MSGLEVEL_CLIENTNOTICE, TXT_PASTE_WARNING, - paste_line_count, + actual_line_count, active_win->active == NULL ? "window" : active_win->active->visible_name); @@ -641,7 +654,11 @@ static gboolean paste_timeout(gpointer data) { paste_was_bracketed_mode = paste_bracketed_mode; - if (paste_line_count == 0) { + /* number of lines after splitting extra-long messages */ + int split_lines = paste_buffer->len / LINE_SPLIT_LIMIT; + + /* Take into account the fact that a line may be split every LINE_SPLIT_LIMIT characters */ + if (paste_line_count == 0 && split_lines <= paste_verify_line_count) { int i; for (i = 0; i < paste_buffer->len; i++) { @@ -650,8 +667,9 @@ static gboolean paste_timeout(gpointer data) } g_array_set_size(paste_buffer, 0); } else if (paste_verify_line_count > 0 && - paste_line_count >= paste_verify_line_count && - active_win->active != NULL) + (paste_line_count >= paste_verify_line_count || + split_lines > paste_verify_line_count) && + active_win->active != NULL) insert_paste_prompt(); else paste_flush(TRUE); From 4d234c175c69d3bcc80d9918fad98e3c6f69d23e Mon Sep 17 00:00:00 2001 From: Lukas Mai Date: Fri, 26 Feb 2016 18:40:51 +0100 Subject: [PATCH 029/140] fix proxy server name --- src/irc/proxy/listen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 3ec83773..ef288201 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -137,7 +137,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client, client->server = server; g_free(client->proxy_address); - client->proxy_address = g_strdup_printf("%*s.proxy", (int)(tag_end - args), args); + client->proxy_address = g_strdup_printf("%.*s.proxy", (int)(tag_end - args), args); } if (g_strcmp0(password, args_pass) != 0) { From 3fc7e4d4ea7faaf3a14206c8b7c46ccc4b96309c Mon Sep 17 00:00:00 2001 From: Lukas Mai Date: Wed, 24 Feb 2016 18:59:00 +0100 Subject: [PATCH 030/140] reindent --- src/irc/proxy/listen.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index ef288201..43cef27f 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -202,7 +202,7 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, if (g_strcmp0(cmd, "PROXY") == 0) { if (g_ascii_strcasecmp(args, "CTCP ON") == 0) { - /* client wants all ctcps */ + /* client wants all ctcps */ client->want_ctcp = 1; for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; @@ -494,12 +494,12 @@ static void sig_server_event(IRC_SERVER_REC *server, const char *line, static void event_connected(IRC_SERVER_REC *server) { GSList *tmp; - const char *chatnet; + const char *chatnet; if (!IS_IRC_SERVER(server)) return; - chatnet = server->connrec->chatnet; + chatnet = server->connrec->chatnet; for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; @@ -508,7 +508,7 @@ static void event_connected(IRC_SERVER_REC *server) (chatnet != NULL && g_ascii_strcasecmp(chatnet, rec->listen->ircnet) == 0))) { proxy_outdata(rec, ":%s NOTICE %s :Connected to server\r\n", - rec->proxy_address, rec->nick); + rec->proxy_address, rec->nick); rec->server = server; proxy_client_reset_nick(rec); } @@ -516,7 +516,7 @@ static void event_connected(IRC_SERVER_REC *server) } static void proxy_server_disconnected(CLIENT_REC *client, - IRC_SERVER_REC *server) + IRC_SERVER_REC *server) { GSList *tmp; @@ -655,9 +655,9 @@ static void add_listen(const char *ircnet, int port) } rec->tag = g_input_add(rec->handle, G_INPUT_READ, - (GInputFunction) sig_listen, rec); + (GInputFunction) sig_listen, rec); - proxy_listens = g_slist_append(proxy_listens, rec); + proxy_listens = g_slist_append(proxy_listens, rec); } static void remove_listen(LISTEN_REC *rec) From 8c1da2890c4ccbeac70d7798f29f00a81a770728 Mon Sep 17 00:00:00 2001 From: Lukas Mai Date: Wed, 24 Feb 2016 19:00:31 +0100 Subject: [PATCH 031/140] irssi proxy: allow listening on unix sockets --- src/common.h | 2 +- src/irc/proxy/listen.c | 188 ++++++++++++++++++++++++++++++----------- src/irc/proxy/proxy.c | 6 +- src/irc/proxy/proxy.h | 5 +- src/perl/irc/Irc.xs | 3 +- 5 files changed, 148 insertions(+), 56 deletions(-) diff --git a/src/common.h b/src/common.h index 966e28d0..729049ab 100644 --- a/src/common.h +++ b/src/common.h @@ -6,7 +6,7 @@ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ -#define IRSSI_ABI_VERSION 1 +#define IRSSI_ABI_VERSION 2 #define DEFAULT_SERVER_ADD_PORT 6667 diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 43cef27f..cde4c0be 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -31,6 +31,8 @@ #include "fe-common/core/printtext.h" /* FIXME: evil. need to do fe-proxy */ +#include + GSList *proxy_listens; GSList *proxy_clients; @@ -39,6 +41,66 @@ static int ignore_next; static int enabled = FALSE; +static int is_all_digits(const char *s) +{ + return strspn(s, "0123456789") == strlen(s); +} + +static GIOChannel *net_listen_unix(const char *path) +{ + struct sockaddr_un sa; + int saved_errno, handle; + + g_return_val_if_fail(path != NULL, NULL); + + handle = socket(AF_UNIX, SOCK_STREAM, 0); + if (handle == -1) { + return NULL; + } + + fcntl(handle, F_SETFL, O_NONBLOCK); + + memset(&sa, '\0', sizeof sa); + sa.sun_family = AF_UNIX; + strncpy(sa.sun_path, path, sizeof sa.sun_path - 1); + if (bind(handle, (struct sockaddr *)&sa, sizeof sa) == -1) { + saved_errno = errno; + goto error_close; + } + + if (listen(handle, 1) == -1) { + saved_errno = errno; + goto error_unlink; + } + + return g_io_channel_new(handle); + +error_unlink: + unlink(sa.sun_path); +error_close: + close(handle); + errno = saved_errno; + return NULL; +} + +static GIOChannel *net_accept_unix(GIOChannel *handle) +{ + struct sockaddr_un sa; + int ret; + socklen_t addrlen; + + g_return_val_if_fail(handle != NULL, NULL); + + addrlen = sizeof sa; + ret = accept(g_io_channel_unix_get_fd(handle), (struct sockaddr *)&sa, &addrlen); + + if (ret < 0) + return NULL; + + fcntl(ret, F_SETFL, O_NONBLOCK); + return g_io_channel_new(ret); +} + static void remove_client(CLIENT_REC *rec) { g_return_if_fail(rec != NULL); @@ -48,13 +110,13 @@ static void remove_client(CLIENT_REC *rec) signal_emit("proxy client disconnected", 1, rec); printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE, - "Proxy: Client %s:%d disconnected", rec->host, rec->port); + "Proxy: Client %s disconnected", rec->addr); g_free(rec->proxy_address); net_sendbuffer_destroy(rec->handle, TRUE); g_source_remove(rec->recv_tag); g_free_not_null(rec->nick); - g_free_not_null(rec->host); + g_free_not_null(rec->addr); g_free(rec); } @@ -160,8 +222,8 @@ static void handle_client_connect_cmd(CLIENT_REC *client, } else { signal_emit("proxy client connected", 1, client); printtext(client->server, NULL, MSGLEVEL_CLIENTNOTICE, - "Proxy: Client %s:%d connected", - client->host, client->port); + "Proxy: Client %s connected", + client->addr); client->connected = TRUE; proxy_dump_data(client); } @@ -370,20 +432,30 @@ static void sig_listen(LISTEN_REC *listen) GIOChannel *handle; char host[MAX_IP_LEN]; int port; + char *addr; g_return_if_fail(listen != NULL); /* accept connection */ - handle = net_accept(listen->handle, &ip, &port); - if (handle == NULL) - return; - net_ip2host(&ip, host); + if (listen->port) { + handle = net_accept(listen->handle, &ip, &port); + if (handle == NULL) + return; + net_ip2host(&ip, host); + addr = g_strdup_printf("%s:%d", host, port); + } else { + /* no port => this is a unix socket */ + handle = net_accept_unix(listen->handle); + if (handle == NULL) + return; + addr = g_strdup("(local)"); + } + sendbuf = net_sendbuffer_create(handle, 0); rec = g_new0(CLIENT_REC, 1); rec->listen = listen; rec->handle = sendbuf; - rec->host = g_strdup(host); - rec->port = port; + rec->addr = addr; if (g_strcmp0(listen->ircnet, "?") == 0) { rec->multiplex = TRUE; rec->proxy_address = g_strdup("multiplex.proxy"); @@ -404,8 +476,8 @@ static void sig_listen(LISTEN_REC *listen) signal_emit("proxy client connecting", 1, rec); printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE, - "Proxy: New client %s:%d on port %d (%s)", - rec->host, rec->port, listen->port, listen->ircnet); + "Proxy: New client %s on port %s (%s)", + rec->addr, listen->port_or_path, listen->ircnet); } static void sig_incoming(IRC_SERVER_REC *server, const char *line) @@ -601,14 +673,19 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg, proxy_outserver_all(server, "PRIVMSG %s :\001ACTION %s\001", target, msg); } -static LISTEN_REC *find_listen(const char *ircnet, int port) +static LISTEN_REC *find_listen(const char *ircnet, int port, const char *port_or_path) { GSList *tmp; for (tmp = proxy_listens; tmp != NULL; tmp = tmp->next) { LISTEN_REC *rec = tmp->data; - if (rec->port == port && + if ((port + ? /* a tcp port */ + rec->port == port + : /* a unix socket path */ + g_strcmp0(rec->port_or_path, port_or_path) == 0 + ) && g_ascii_strcasecmp(rec->ircnet, ircnet) == 0) return rec; } @@ -616,43 +693,48 @@ static LISTEN_REC *find_listen(const char *ircnet, int port) return NULL; } -static void add_listen(const char *ircnet, int port) +static void add_listen(const char *ircnet, int port, const char *port_or_path) { LISTEN_REC *rec; IPADDR ip4, ip6, *my_ip; + GIOChannel *handle; - if (port <= 0 || *ircnet == '\0') + if (*port_or_path == '\0' || port < 0 || *ircnet == '\0') return; - /* bind to specific host/ip? */ - my_ip = NULL; - if (*settings_get_str("irssiproxy_bind") != '\0') { - if (net_gethostbyname(settings_get_str("irssiproxy_bind"), - &ip4, &ip6) != 0) { - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, - "Proxy: can not resolve '%s' - aborting", - settings_get_str("irssiproxy_bind")); - return; - } + if (port == 0) { + /* listening on a unix socket */ + handle = net_listen_unix(port_or_path); + } else { + /* bind to specific host/ip? */ + my_ip = NULL; + if (*settings_get_str("irssiproxy_bind") != '\0') { + if (net_gethostbyname(settings_get_str("irssiproxy_bind"), + &ip4, &ip6) != 0) { + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, + "Proxy: can not resolve '%s' - aborting", + settings_get_str("irssiproxy_bind")); + return; + } - my_ip = ip6.family == 0 ? &ip4 : ip4.family == 0 || - settings_get_bool("resolve_prefer_ipv6") ? &ip6 : &ip4; + my_ip = ip6.family == 0 ? &ip4 : ip4.family == 0 || + settings_get_bool("resolve_prefer_ipv6") ? &ip6 : &ip4; + } + handle = net_listen(my_ip, &port); + } + + if (handle == NULL) { + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, + "Proxy: Listen in port %s failed: %s", + port_or_path, g_strerror(errno)); + return; } rec = g_new0(LISTEN_REC, 1); + rec->handle = handle; rec->ircnet = g_strdup(ircnet); rec->port = port; - - rec->handle = net_listen(my_ip, &rec->port); - - if (rec->handle == NULL) { - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, - "Proxy: Listen in port %d failed: %s", - rec->port, g_strerror(errno)); - g_free(rec->ircnet); - g_free(rec); - return; - } + rec->port_or_path = g_strdup(port_or_path); rec->tag = g_input_add(rec->handle, G_INPUT_READ, (GInputFunction) sig_listen, rec); @@ -667,8 +749,13 @@ static void remove_listen(LISTEN_REC *rec) while (rec->clients != NULL) remove_client(rec->clients->data); + /* remove unix socket because bind wants to (re)create it */ + if (rec->port == 0) + unlink(rec->port_or_path); + net_disconnect(rec->handle); g_source_remove(rec->tag); + g_free(rec->port_or_path); g_free(rec->ircnet); g_free(rec); } @@ -678,7 +765,7 @@ static void read_settings(void) LISTEN_REC *rec; GSList *remove_listens = NULL; GSList *add_listens = NULL; - char **ports, **tmp, *ircnet, *port; + char **ports, **tmp, *ircnet, *port_or_path; int portnum; remove_listens = g_slist_copy(proxy_listens); @@ -686,20 +773,25 @@ static void read_settings(void) ports = g_strsplit(settings_get_str("irssiproxy_ports"), " ", -1); for (tmp = ports; *tmp != NULL; tmp++) { ircnet = *tmp; - port = strchr(ircnet, '='); - if (port == NULL) + port_or_path = strchr(ircnet, '='); + if (port_or_path == NULL) continue; - *port++ = '\0'; - portnum = atoi(port); - if (portnum <= 0) - continue; + *port_or_path++ = '\0'; + if (is_all_digits(port_or_path)) { + portnum = atoi(port_or_path); + if (portnum <= 0) + continue; + } else { + portnum = 0; + } - rec = find_listen(ircnet, portnum); + rec = find_listen(ircnet, portnum, port_or_path); if (rec == NULL) { rec = g_new0(LISTEN_REC, 1); rec->ircnet = ircnet; /* borrow */ rec->port = portnum; + rec->port_or_path = port_or_path; /* borrow */ add_listens = g_slist_prepend(add_listens, rec); } else { /* remove from the list of listens to remove == keep it */ @@ -714,7 +806,7 @@ static void read_settings(void) while (add_listens != NULL) { rec = add_listens->data; - add_listen(rec->ircnet, rec->port); + add_listen(rec->ircnet, rec->port, rec->port_or_path); add_listens = g_slist_remove(add_listens, rec); g_free(rec); } diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c index 50a41b21..1a714045 100644 --- a/src/irc/proxy/proxy.c +++ b/src/irc/proxy/proxy.c @@ -44,10 +44,10 @@ static void cmd_irssiproxy_status(const char *data, IRC_SERVER_REC *server) CLIENT_REC *rec = tmp->data; printtext(server, NULL, MSGLEVEL_CLIENTNOTICE, - " %s:%d connect%s to %d (%s)", - rec->host, rec->port, + " %s connect%s to %s (%s)", + rec->addr, rec->connected ? "ed" : "ing", - rec->listen->port, rec->listen->ircnet); + rec->listen->port_or_path, rec->listen->ircnet); } } diff --git a/src/irc/proxy/proxy.h b/src/irc/proxy/proxy.h index f37e9c95..620ea605 100644 --- a/src/irc/proxy/proxy.h +++ b/src/irc/proxy/proxy.h @@ -9,17 +9,18 @@ typedef struct { int port; + char *port_or_path; char *ircnet; int tag; GIOChannel *handle; GSList *clients; + } LISTEN_REC; typedef struct { - char *nick, *host; - int port; + char *nick, *addr; NET_SENDBUF_REC *handle; int recv_tag; char *proxy_address; diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs index 4217b4eb..3f8ccc2e 100644 --- a/src/perl/irc/Irc.xs +++ b/src/perl/irc/Irc.xs @@ -149,8 +149,7 @@ static void perl_notifylist_fill_hash(HV *hv, NOTIFYLIST_REC *notify) static void perl_client_fill_hash(HV *hv, CLIENT_REC *client) { (void) hv_store(hv, "nick", 4, new_pv(client->nick), 0); - (void) hv_store(hv, "host", 4, new_pv(client->host), 0); - (void) hv_store(hv, "port", 4, newSViv(client->port), 0); + (void) hv_store(hv, "addr", 4, new_pv(client->addr), 0); (void) hv_store(hv, "proxy_address", 13, new_pv(client->proxy_address), 0); (void) hv_store(hv, "server", 6, iobject_bless(client->server), 0); (void) hv_store(hv, "pass_sent", 9, newSViv(client->pass_sent), 0); From 4baefd25747df116c19ea1301c5fe8fb7eef3716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mantas=20Mikul=C4=97nas?= Date: Tue, 8 Mar 2016 23:00:20 +0200 Subject: [PATCH 032/140] Fix SASL EXTERNAL authentication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "AUTHENTICATE" command is always required – it's part of the IRCv3 SASL framing. RFC 4422 only documents the Base64 payload. --- src/irc/core/sasl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index a04eaf45..8fba9ba2 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -145,7 +145,7 @@ static void sasl_step(IRC_SERVER_REC *server, const char *data, const char *from case SASL_MECHANISM_EXTERNAL: /* Empty response */ - irc_send_cmdv(server, "+"); + irc_send_cmdv(server, "AUTHENTICATE +"); break; } From e853392f430b9635cd7e8ada28c68426c2625298 Mon Sep 17 00:00:00 2001 From: dequis Date: Fri, 11 Mar 2016 14:55:31 -0300 Subject: [PATCH 033/140] Remove sasl timeout source when the server disconnects --- src/irc/core/sasl.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index 8fba9ba2..db099368 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -153,6 +153,20 @@ static void sasl_step(IRC_SERVER_REC *server, const char *data, const char *from server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server); } +static void sasl_disconnected(IRC_SERVER_REC *server) +{ + g_return_if_fail(server != NULL); + + if (!IS_IRC_SERVER(server)) { + return; + } + + if (server->sasl_timeout != -1) { + g_source_remove(server->sasl_timeout); + server->sasl_timeout = -1; + } +} + void sasl_init(void) { signal_add_first("server cap ack sasl", (SIGNAL_FUNC) sasl_start); @@ -163,6 +177,7 @@ void sasl_init(void) signal_add_first("event 905", (SIGNAL_FUNC) sasl_fail); signal_add_first("event 906", (SIGNAL_FUNC) sasl_fail); signal_add_first("event 907", (SIGNAL_FUNC) sasl_already); + signal_add_first("server disconnected", (SIGNAL_FUNC) sasl_disconnected); } void sasl_deinit(void) @@ -175,4 +190,5 @@ void sasl_deinit(void) signal_remove("event 905", (SIGNAL_FUNC) sasl_fail); signal_remove("event 906", (SIGNAL_FUNC) sasl_fail); signal_remove("event 907", (SIGNAL_FUNC) sasl_already); + signal_remove("server disconnected", (SIGNAL_FUNC) sasl_disconnected); } From be733d24824fe2a3502a1e4ab76d50699052dd65 Mon Sep 17 00:00:00 2001 From: Will Storey Date: Sun, 13 Mar 2016 13:28:04 -0700 Subject: [PATCH 034/140] Clear error queue before SSL I/O operations Otherwise we can see errors that are not related to the operation we check for. SSL_get_error() inspects the thread's error queue. See https://www.openssl.org/docs/manmaster/ssl/SSL_get_error.html for more information. --- src/core/network-openssl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 465c4154..d0f23253 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -289,6 +289,7 @@ static GIOStatus irssi_ssl_read(GIOChannel *handle, gchar *buf, gsize len, gsize const char *errstr; gchar *errmsg; + ERR_clear_error(); ret1 = SSL_read(chan->ssl, buf, len); if(ret1 <= 0) { @@ -334,6 +335,7 @@ static GIOStatus irssi_ssl_write(GIOChannel *handle, const gchar *buf, gsize len const char *errstr; gchar *errmsg; + ERR_clear_error(); ret1 = SSL_write(chan->ssl, (const char *)buf, len); if(ret1 <= 0) { @@ -581,6 +583,7 @@ int irssi_ssl_handshake(GIOChannel *handle) X509 *cert; const char *errstr; + ERR_clear_error(); ret = SSL_connect(chan->ssl); if (ret <= 0) { err = SSL_get_error(chan->ssl, ret); From 8ab6bdf2ce884fa7363272805287c341b2b2fb01 Mon Sep 17 00:00:00 2001 From: Will Storey Date: Sun, 13 Mar 2016 15:09:52 -0700 Subject: [PATCH 035/140] Add clear error calls to irssi_ssl_get_iochannel --- src/core/network-openssl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index d0f23253..a18e6fc7 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -473,6 +473,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ if(!(fd = g_io_channel_unix_get_fd(handle))) return NULL; + ERR_clear_error(); ctx = SSL_CTX_new(SSLv23_client_method()); if (ctx == NULL) { g_error("Could not allocate memory for SSL context"); @@ -491,6 +492,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ scert = convert_home(mycert); if (mypkey && *mypkey) spkey = convert_home(mypkey); + ERR_clear_error(); if (! SSL_CTX_use_certificate_file(ctx, scert, SSL_FILETYPE_PEM)) g_warning("Loading of client certificate '%s' failed: %s", mycert, ERR_reason_error_string(ERR_get_error())); else if (! SSL_CTX_use_PrivateKey_file(ctx, spkey ? spkey : scert, SSL_FILETYPE_PEM)) From 27c37cb3f39578b473a0684e6e55bf23d1910903 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sun, 13 Mar 2016 22:04:59 +0100 Subject: [PATCH 036/140] Return -1 from null-test to comply with the rest of strarray_find --- src/core/misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/misc.c b/src/core/misc.c index aaa470f5..c26610ec 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -169,8 +169,8 @@ int strarray_find(char **array, const char *item) char **tmp; int index; - g_return_val_if_fail(array != NULL, 0); - g_return_val_if_fail(item != NULL, 0); + g_return_val_if_fail(array != NULL, -1); + g_return_val_if_fail(item != NULL, -1); index = 0; for (tmp = array; *tmp != NULL; tmp++, index++) { From 94b823c3cd410abb2fa54ecbcf298550d5e2ba88 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Fri, 11 Mar 2016 09:12:38 +0100 Subject: [PATCH 037/140] Use glob matching for activity_hide_targets spaces vs tabs! strarray_find* needs to return -1 if no index found --- src/core/misc.c | 18 ++++++++++++++++++ src/core/misc.h | 1 + src/fe-common/core/fe-common-core.c | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/core/misc.c b/src/core/misc.c index aaa470f5..2284d3b1 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -181,6 +181,24 @@ int strarray_find(char **array, const char *item) return -1; } + +int strarray_find_glob(char **array, const char *item) +{ + char **tmp; + int index; + + g_return_val_if_fail(array != NULL, -1); + g_return_val_if_fail(item != NULL, -1); + + index = 0; + for (tmp = array; *tmp != NULL; tmp++, index++) { + if (g_pattern_match_simple(*tmp, item)) + return index; + } + + return -1; +} + GSList *gslist_find_string(GSList *list, const char *key) { for (; list != NULL; list = list->next) diff --git a/src/core/misc.h b/src/core/misc.h index 7e78d3b9..dd8bb14c 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -111,6 +111,7 @@ char *replace_chars(char *str, char from, char to); int strarray_length(char **array); /* return index of `item' in `array' or -1 if not found */ int strarray_find(char **array, const char *item); +int strarray_find_glob(char **array, const char *item); /* string -> uoff_t */ uoff_t str_to_uofft(const char *str); diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index ee7f9424..f0549358 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -464,7 +464,7 @@ gboolean strarray_find_dest(char **array, const TEXT_DEST_REC *dest) if (dest->server_tag != NULL) { char *tagtarget = g_strdup_printf("%s/%s", dest->server_tag, dest->target); - int ret = strarray_find(array, tagtarget); + int ret = strarray_find_glob(array, tagtarget); g_free(tagtarget); if (ret != -1) return TRUE; From bcebed5a72308f57de8f96f6ab9ad5ccad93a811 Mon Sep 17 00:00:00 2001 From: KindOne Date: Mon, 14 Mar 2016 21:23:37 -0400 Subject: [PATCH 038/140] Replace spaces with tabs --- src/core/chat-commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 8e881679..7f000cf5 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -117,8 +117,8 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, if (g_hash_table_lookup(optlist, "!") != NULL) conn->no_autojoin_channels = TRUE; - if (g_hash_table_lookup(optlist, "noautosendcmd") != NULL) - conn->no_autosendcmd = TRUE; + if (g_hash_table_lookup(optlist, "noautosendcmd") != NULL) + conn->no_autosendcmd = TRUE; if (g_hash_table_lookup(optlist, "noproxy") != NULL) g_free_and_null(conn->proxy); From f6c2805b91161a01378c9bbe853521c08d460c60 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 17 Mar 2016 22:27:05 +0100 Subject: [PATCH 039/140] Do not assume any default value for statusmsg. If the server didn't send it then just skip the check, the old value it defaulted to was possibly overlapping with the CHANTYPES leading to an incorrect behaviour. Fixes #435. --- src/irc/core/irc-servers.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 81f0c269..d6fb8018 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -81,12 +81,12 @@ static int ischannel_func(SERVER_REC *server, const char *data) chantypes = g_hash_table_lookup(irc_server->isupport, "chantypes"); if (chantypes == NULL) chantypes = "#&!+"; /* normal, local, secure, modeless */ - statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg"); - if (statusmsg == NULL) - statusmsg = "@+"; - while (strchr(statusmsg, *data) != NULL) - data++; + statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg"); + if (statusmsg != NULL) { + while (strchr(statusmsg, *data) != NULL) + data++; + } return strchr(chantypes, *data) != NULL; } From 857e27aef6d04edc1e47d52d74031ba279d2da1a Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Thu, 17 Mar 2016 23:58:46 +0100 Subject: [PATCH 040/140] Don't use glob matching, just regular string comparisons --- src/core/misc.c | 20 +------------------- src/core/misc.h | 1 - src/fe-common/core/fe-common-core.c | 13 +++++++++++-- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/core/misc.c b/src/core/misc.c index 2284d3b1..c26610ec 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -169,30 +169,12 @@ int strarray_find(char **array, const char *item) char **tmp; int index; - g_return_val_if_fail(array != NULL, 0); - g_return_val_if_fail(item != NULL, 0); - - index = 0; - for (tmp = array; *tmp != NULL; tmp++, index++) { - if (g_ascii_strcasecmp(*tmp, item) == 0) - return index; - } - - return -1; -} - - -int strarray_find_glob(char **array, const char *item) -{ - char **tmp; - int index; - g_return_val_if_fail(array != NULL, -1); g_return_val_if_fail(item != NULL, -1); index = 0; for (tmp = array; *tmp != NULL; tmp++, index++) { - if (g_pattern_match_simple(*tmp, item)) + if (g_ascii_strcasecmp(*tmp, item) == 0) return index; } diff --git a/src/core/misc.h b/src/core/misc.h index dd8bb14c..7e78d3b9 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -111,7 +111,6 @@ char *replace_chars(char *str, char from, char to); int strarray_length(char **array); /* return index of `item' in `array' or -1 if not found */ int strarray_find(char **array, const char *item); -int strarray_find_glob(char **array, const char *item); /* string -> uoff_t */ uoff_t str_to_uofft(const char *str); diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index f0549358..1b2ab1e2 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -459,12 +459,21 @@ gboolean strarray_find_dest(char **array, const TEXT_DEST_REC *dest) { g_return_val_if_fail(array != NULL, FALSE); + if (strarray_find(array, "*") != -1) + return TRUE; + if (strarray_find(array, dest->target) != -1) return TRUE; if (dest->server_tag != NULL) { - char *tagtarget = g_strdup_printf("%s/%s", dest->server_tag, dest->target); - int ret = strarray_find_glob(array, tagtarget); + char *tagtarget = g_strdup_printf("%s/%s", dest->server_tag, "*"); + int ret = strarray_find(array, tagtarget); + g_free(tagtarget); + if (ret != -1) + return TRUE; + + tagtarget = g_strdup_printf("%s/%s", dest->server_tag, dest->target); + ret = strarray_find(array, tagtarget); g_free(tagtarget); if (ret != -1) return TRUE; From f31d37a85271e0196aeefd409f0ab361ffd8c2ff Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 18 Mar 2016 22:50:00 +0100 Subject: [PATCH 041/140] Make ischannel_func return false for empty strings --- src/irc/core/irc-servers.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index d6fb8018..1df95f70 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -78,17 +78,23 @@ static int ischannel_func(SERVER_REC *server, const char *data) IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server; char *chantypes, *statusmsg; + g_return_val_if_fail(data != NULL, FALSE); + + /* empty string is no channel */ + if (*data == '\0') + return FALSE; + chantypes = g_hash_table_lookup(irc_server->isupport, "chantypes"); if (chantypes == NULL) chantypes = "#&!+"; /* normal, local, secure, modeless */ statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg"); - if (statusmsg != NULL) { - while (strchr(statusmsg, *data) != NULL) - data++; - } + if (statusmsg != NULL) + data += strspn(data, statusmsg); - return strchr(chantypes, *data) != NULL; + /* strchr(3) considers the trailing NUL as part of the string, make sure + * we didn't advance too much. */ + return *data != '\0' && strchr(chantypes, *data) != NULL; } static char **split_line(const SERVER_REC *server, const char *line, From 6745dd6159afc6ff220d09d7adc1923218fa756b Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 18 Mar 2016 20:18:58 +0100 Subject: [PATCH 042/140] Throw an error when a chatnet has no available url If you type /connect and the chatnet has no url available let's just throw an error instead of trying to process as a url. --- src/core/chat-commands.c | 7 +++++++ src/core/commands.h | 3 ++- src/core/servers-setup.c | 2 ++ src/fe-common/core/fe-core-commands.c | 3 ++- src/fe-common/core/module-formats.c | 1 + src/fe-common/core/module-formats.h | 1 + 6 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 7f000cf5..a9404fa3 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -73,6 +73,13 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, conn = server_create_conn(proto != NULL ? proto->id : -1, addr, atoi(portstr), chatnet, password, nick); + if (conn == NULL) { + signal_emit("error command", 1, + GINT_TO_POINTER(CMDERR_NO_SERVER_DEFINED)); + cmd_params_free(free_arg); + return NULL; + } + if (proto == NULL) proto = chat_protocol_find_id(conn->chat_type); diff --git a/src/core/commands.h b/src/core/commands.h index 72105ad3..93d6276b 100644 --- a/src/core/commands.h +++ b/src/core/commands.h @@ -41,7 +41,8 @@ enum { CMDERR_INVALID_TIME, /* invalid time specification */ CMDERR_INVALID_CHARSET, /* invalid charset specification */ CMDERR_EVAL_MAX_RECURSE, /* eval hit recursion limit */ - CMDERR_PROGRAM_NOT_FOUND /* program not found */ + CMDERR_PROGRAM_NOT_FOUND, /* program not found */ + CMDERR_NO_SERVER_DEFINED, /* no server has been defined for a given chatnet */ }; /* Return the full command for `alias' */ diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 4a048282..990d2d4b 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -323,6 +323,8 @@ server_create_conn(int chat_type, const char *dest, int port, rec = create_chatnet_conn(chatrec->name, port, password, nick); if (rec != NULL) return rec; + /* The chatnet has no url to connect to */ + return NULL; } chatrec = chatnet == NULL ? NULL : chatnet_find(chatnet); diff --git a/src/fe-common/core/fe-core-commands.c b/src/fe-common/core/fe-core-commands.c index 7b1d7b94..97a246ec 100644 --- a/src/fe-common/core/fe-core-commands.c +++ b/src/fe-common/core/fe-core-commands.c @@ -51,7 +51,8 @@ static int ret_texts[] = { TXT_INVALID_TIME, TXT_INVALID_CHARSET, TXT_EVAL_MAX_RECURSE, - TXT_PROGRAM_NOT_FOUND + TXT_PROGRAM_NOT_FOUND, + TXT_NO_SERVER_DEFINED, }; int command_hide_output; diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index e6d32b6d..b897b0c6 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -223,6 +223,7 @@ FORMAT_REC fecommon_core_formats[] = { { "invalid_charset", "Invalid charset: $0", 1, { 0 } }, { "eval_max_recurse", "/eval hit maximum recursion limit", 0 }, { "program_not_found", "Could not find file or file is not executable", 0 }, + { "no_server_defined", "No servers defined for this network, see /help server for how to add one", 0 }, /* ---- */ { NULL, "Themes", 0 }, diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h index 3f06bb97..de1e13f2 100644 --- a/src/fe-common/core/module-formats.h +++ b/src/fe-common/core/module-formats.h @@ -192,6 +192,7 @@ enum { TXT_INVALID_CHARSET, TXT_EVAL_MAX_RECURSE, TXT_PROGRAM_NOT_FOUND, + TXT_NO_SERVER_DEFINED, TXT_FILL_11, From 8394973d5a3f37523e95fb5b51620de9284d743f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 20 Mar 2016 12:16:48 +0100 Subject: [PATCH 043/140] Bump the ABI version Since a new format has been added. --- src/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.h b/src/common.h index 729049ab..33dbd481 100644 --- a/src/common.h +++ b/src/common.h @@ -6,7 +6,7 @@ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ -#define IRSSI_ABI_VERSION 2 +#define IRSSI_ABI_VERSION 3 #define DEFAULT_SERVER_ADD_PORT 6667 From 550fe6f010f682d352077579d5056609a68e9814 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 20 Mar 2016 21:47:02 +0100 Subject: [PATCH 044/140] Use 0 as a sentinel value for sasl_timeout If sasl_timeout is never initialized with a valid timeout id then calling /disconnect on the server calls g_source_remove() with 0 as tag, causing an harmless error message to be printed. Beside that, the sasl_timeout field is defined as a unsigned int. We can use 0 as sentiel since g_timeout_add returns tags that are always greater than zero. --- src/irc/core/sasl.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index db099368..b74b6a8c 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -34,7 +34,7 @@ static gboolean sasl_timeout(IRC_SERVER_REC *server) irc_send_cmd_now(server, "AUTHENTICATE *"); cap_finish_negotiation(server); - server->sasl_timeout = -1; + server->sasl_timeout = 0; signal_emit("server sasl failure", 2, server, "The authentication timed out"); @@ -64,9 +64,9 @@ static void sasl_fail(IRC_SERVER_REC *server, const char *data, const char *from char *params, *error; /* Stop any pending timeout, if any */ - if (server->sasl_timeout != -1) { + if (server->sasl_timeout != 0) { g_source_remove(server->sasl_timeout); - server->sasl_timeout = -1; + server->sasl_timeout = 0; } params = event_get_params(data, 2, NULL, &error); @@ -81,9 +81,9 @@ static void sasl_fail(IRC_SERVER_REC *server, const char *data, const char *from static void sasl_already(IRC_SERVER_REC *server, const char *data, const char *from) { - if (server->sasl_timeout != -1) { + if (server->sasl_timeout != 0) { g_source_remove(server->sasl_timeout); - server->sasl_timeout = -1; + server->sasl_timeout = 0; } signal_emit("server sasl success", 1, server); @@ -94,9 +94,9 @@ static void sasl_already(IRC_SERVER_REC *server, const char *data, const char *f static void sasl_success(IRC_SERVER_REC *server, const char *data, const char *from) { - if (server->sasl_timeout != -1) { + if (server->sasl_timeout != 0) { g_source_remove(server->sasl_timeout); - server->sasl_timeout = -1; + server->sasl_timeout = 0; } signal_emit("server sasl success", 1, server); @@ -114,9 +114,9 @@ static void sasl_step(IRC_SERVER_REC *server, const char *data, const char *from conn = server->connrec; /* Stop the timer */ - if (server->sasl_timeout != -1) { + if (server->sasl_timeout != 0) { g_source_remove(server->sasl_timeout); - server->sasl_timeout = -1; + server->sasl_timeout = 0; } switch (conn->sasl_mechanism) { @@ -161,9 +161,9 @@ static void sasl_disconnected(IRC_SERVER_REC *server) return; } - if (server->sasl_timeout != -1) { + if (server->sasl_timeout != 0) { g_source_remove(server->sasl_timeout); - server->sasl_timeout = -1; + server->sasl_timeout = 0; } } From 132d3c49f302a87d1357ba91ba715faa6bfcea29 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Sun, 20 Mar 2016 22:39:06 +0100 Subject: [PATCH 045/140] strip less whitespace from commands fixes #445 --- src/fe-common/core/completion.c | 2 +- src/fe-common/core/fe-settings.c | 2 +- src/irc/dcc/dcc.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index 1e7833a4..861054b5 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -762,7 +762,7 @@ static void cmd_completion(const char *data) int len; if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | - PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, + PARAM_FLAG_GETREST, "completion", &optlist, &key, &value)) return; diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index 3bb43bf7..b689cbf9 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -109,7 +109,7 @@ static void cmd_set(char *data) SETTINGS_REC *rec; if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | - PARAM_FLAG_OPTIONS | PARAM_FLAG_STRIP_TRAILING_WS, + PARAM_FLAG_OPTIONS, "set", &optlist, &key, &value)) return; diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index 7f35585e..17f6c477 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -496,8 +496,8 @@ static void cmd_dcc_close(char *data, IRC_SERVER_REC *server) g_return_if_fail(data != NULL); - if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST | - PARAM_FLAG_STRIP_TRAILING_WS, &typestr, &nick, &arg)) + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, + &typestr, &nick, &arg)) return; if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); From 7baf3a28bbcc1f92707ecb06f1d8e648388a474c Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Sun, 20 Mar 2016 22:43:12 +0100 Subject: [PATCH 046/140] correct quoting in /help dcc --- docs/help/in/dcc.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/help/in/dcc.in b/docs/help/in/dcc.in index 649cb12b..dac31e58 100644 --- a/docs/help/in/dcc.in +++ b/docs/help/in/dcc.in @@ -36,10 +36,10 @@ %9Examples:%9 /DCC CHAT mike - /DCC GET bob 'summer vacation.mkv' - /DCC SEND sarah documents/resume.pdf + /DCC GET bob summer vacation.mkv + /DCC SEND sarah "summer vacation.mkv" /DCC CLOSE get mike - /DCC CLOSE send bob 'summer vacation.mkv' + /DCC CLOSE send bob summer vacation.mkv %9See also:%9 CD From 117c890d98d54fdee85a56f851acd6f4b3bd3be3 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 22 Mar 2016 14:43:31 +0100 Subject: [PATCH 047/140] cutbuffer: do not unconditionally use replace when noop was requested --- src/fe-text/gui-entry.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 27778b2b..f275c235 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -582,7 +582,8 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_ if (size == 0 || entry->pos < size) return; - if (entry->cutbuffer_len == 0) { + if (update_cutbuffer != CUTBUFFER_UPDATE_NOOP + && entry->cutbuffer_len == 0) { update_cutbuffer = CUTBUFFER_UPDATE_REPLACE; } int cutbuffer_new_size = entry->cutbuffer_len + size; From 938d0071c6119f7ec9aeaa88913c47f7af267131 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 22 Mar 2016 15:21:20 +0100 Subject: [PATCH 048/140] fix race condition in terminal init remove the tcgetattr call to a single time on irssi load instead of querying it each time. Fixes #450 --- src/fe-text/terminfo-core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c index 60927f1a..4db68cc7 100644 --- a/src/fe-text/terminfo-core.c +++ b/src/fe-text/terminfo-core.c @@ -496,7 +496,7 @@ void terminfo_setup_colors(TERM_REC *term, int force) } } -static void terminfo_input_init(TERM_REC *term) +static void terminfo_input_init0(TERM_REC *term) { tcgetattr(fileno(term->in), &term->old_tio); memcpy(&term->tio, &term->old_tio, sizeof(term->tio)); @@ -518,8 +518,11 @@ static void terminfo_input_init(TERM_REC *term) term->tio.c_cc[VSUSP] = _POSIX_VDISABLE; #endif - tcsetattr(fileno(term->in), TCSADRAIN, &term->tio); +} +static void terminfo_input_init(TERM_REC *term) +{ + tcsetattr(fileno(term->in), TCSADRAIN, &term->tio); } static void terminfo_input_deinit(TERM_REC *term) @@ -673,6 +676,7 @@ static int term_setup(TERM_REC *term) term->beep = term->TI_bel ? _beep : _ignore; terminfo_setup_colors(term, FALSE); + terminfo_input_init0(term); terminfo_cont(term); return 1; } From e5ee243ab6ff7f640bdd45a232ad81ed97520a46 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 22 Mar 2016 15:45:08 +0100 Subject: [PATCH 049/140] Simplify some logic in server_create_conn --- src/core/servers-setup.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 990d2d4b..0cecfece 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -321,10 +321,8 @@ server_create_conn(int chat_type, const char *dest, int port, chatrec = chatnet_find(dest); if (chatrec != NULL) { rec = create_chatnet_conn(chatrec->name, port, password, nick); - if (rec != NULL) - return rec; - /* The chatnet has no url to connect to */ - return NULL; + /* If rec is NULL the chatnet has no url to connect to */ + return rec; } chatrec = chatnet == NULL ? NULL : chatnet_find(chatnet); From 8b54366d9525d94ae4b1d0d6914b22b7bf73112e Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 21 Mar 2016 15:23:12 +0100 Subject: [PATCH 050/140] Support quoted filenames in some /DCC commands --- src/irc/dcc/dcc-get.c | 8 +++++--- src/irc/dcc/dcc.c | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c index a8b1c967..ac281683 100644 --- a/src/irc/dcc/dcc-get.c +++ b/src/irc/dcc/dcc-get.c @@ -526,14 +526,14 @@ void cmd_dcc_receive(const char *data, DCC_GET_FUNC accept_func, { GET_DCC_REC *dcc; GSList *tmp, *next; - char *nick, *fname; + char *nick, *arg, *fname; void *free_arg; int found; g_return_if_fail(data != NULL); - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, - &nick, &fname)) + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | + PARAM_FLAG_STRIP_TRAILING_WS, &nick, &arg)) return; if (*nick == '\0') { @@ -548,6 +548,8 @@ void cmd_dcc_receive(const char *data, DCC_GET_FUNC accept_func, return; } + fname = cmd_get_quoted_param(&arg); + found = FALSE; for (tmp = dcc_conns; tmp != NULL; tmp = next) { GET_DCC_REC *dcc = tmp->data; diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index 17f6c477..c51f7c7a 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -490,7 +490,7 @@ static void event_no_such_nick(IRC_SERVER_REC *server, char *data) static void cmd_dcc_close(char *data, IRC_SERVER_REC *server) { GSList *tmp, *next; - char *typestr, *nick, *arg; + char *typestr, *nick, *arg, *fname; void *free_arg; int found, type; @@ -510,13 +510,15 @@ static void cmd_dcc_close(char *data, IRC_SERVER_REC *server) return; } + fname = cmd_get_quoted_param(&arg); + found = FALSE; for (tmp = dcc_conns; tmp != NULL; tmp = next) { DCC_REC *dcc = tmp->data; next = tmp->next; if (dcc->type == type && g_ascii_strcasecmp(dcc->nick, nick) == 0 && - (*arg == '\0' || g_strcmp0(dcc->arg, arg) == 0)) { + (*fname == '\0' || g_strcmp0(dcc->arg, fname) == 0)) { dcc_reject(dcc, server); found = TRUE; } From be93c8d5bee1b923faa63e13957764e3f06e2ded Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 22 Mar 2016 16:03:05 +0100 Subject: [PATCH 051/140] Update the documentation about DCC --- docs/help/in/dcc.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/help/in/dcc.in b/docs/help/in/dcc.in index dac31e58..18a77ee9 100644 --- a/docs/help/in/dcc.in +++ b/docs/help/in/dcc.in @@ -36,10 +36,10 @@ %9Examples:%9 /DCC CHAT mike - /DCC GET bob summer vacation.mkv + /DCC GET bob "summer vacation.mkv" /DCC SEND sarah "summer vacation.mkv" /DCC CLOSE get mike - /DCC CLOSE send bob summer vacation.mkv + /DCC CLOSE send bob "summer vacation.mkv" %9See also:%9 CD From 35d255fc8c2bc585bacbe59afb8cf9c6cc3cadc8 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 22 Mar 2016 16:05:14 +0100 Subject: [PATCH 052/140] Properly toggle bracketed paste mode on stop/cont Fixes #449 --- src/common.h | 2 +- src/fe-text/term-terminfo.c | 8 -------- src/fe-text/terminfo-core.c | 23 +++++++++++++++++++++++ src/fe-text/terminfo-core.h | 3 +++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/common.h b/src/common.h index 729049ab..33dbd481 100644 --- a/src/common.h +++ b/src/common.h @@ -6,7 +6,7 @@ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ -#define IRSSI_ABI_VERSION 2 +#define IRSSI_ABI_VERSION 3 #define DEFAULT_SERVER_ADD_PORT 6667 diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c index 3582b9e4..27be904e 100644 --- a/src/fe-text/term-terminfo.c +++ b/src/fe-text/term-terminfo.c @@ -710,11 +710,3 @@ void term_gets(GArray *buffer, int *line_count) } } } - -void term_set_bracketed_paste_mode(int enable) -{ - if (enable) - tputs("\e[?2004h", 0, term_putchar); - else - tputs("\e[?2004l", 0, term_putchar); -} diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c index 60927f1a..086c8801 100644 --- a/src/fe-text/terminfo-core.c +++ b/src/fe-text/terminfo-core.c @@ -395,6 +395,14 @@ static void _ignore_parm(TERM_REC *term, int param) { } +static void term_dec_set_bracketed_paste_mode(int enable) +{ + if (enable) + tputs("\e[?2004h", 0, term_putchar); + else + tputs("\e[?2004l", 0, term_putchar); +} + static void term_fill_capabilities(TERM_REC *term) { int i, ival; @@ -535,6 +543,9 @@ void terminfo_cont(TERM_REC *term) if (term->TI_smkx) tput(tparm(term->TI_smkx)); + if (term->bracketed_paste_enabled) + term_dec_set_bracketed_paste_mode(TRUE); + terminfo_input_init(term); } @@ -545,6 +556,9 @@ void terminfo_stop(TERM_REC *term) /* move cursor to bottom of the screen */ terminfo_move(0, term->height-1); + if (term->bracketed_paste_enabled) + term_dec_set_bracketed_paste_mode(FALSE); + /* stop cup-mode */ if (term->TI_rmcup) tput(tparm(term->TI_rmcup)); @@ -677,6 +691,15 @@ static int term_setup(TERM_REC *term) return 1; } +void term_set_bracketed_paste_mode(int enable) +{ + if (current_term->bracketed_paste_enabled == enable) + return; + + current_term->bracketed_paste_enabled = enable; + term_dec_set_bracketed_paste_mode(enable); +} + TERM_REC *terminfo_core_init(FILE *in, FILE *out) { TERM_REC *old_term, *term; diff --git a/src/fe-text/terminfo-core.h b/src/fe-text/terminfo-core.h index 21398791..0ef280a1 100644 --- a/src/fe-text/terminfo-core.h +++ b/src/fe-text/terminfo-core.h @@ -92,6 +92,9 @@ struct _TERM_REC { /* Keyboard-transmit mode */ const char *TI_smkx; const char *TI_rmkx; + + /* Terminal mode states */ + int bracketed_paste_enabled; }; extern TERM_REC *current_term; From 897016131eb2712095a7facaf9ab307164976450 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 21 Mar 2016 14:19:43 +0100 Subject: [PATCH 053/140] Don't call terminfo_cont() twice on resume Fixes some weirdness when using ^Z with zsh. --- src/fe-text/term-terminfo.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c index 3582b9e4..ed9c8d32 100644 --- a/src/fe-text/term-terminfo.c +++ b/src/fe-text/term-terminfo.c @@ -611,8 +611,6 @@ void term_stop(void) { terminfo_stop(current_term); kill(getpid(), SIGTSTP); - terminfo_cont(current_term); - irssi_redraw(); } static int input_utf8(const unsigned char *buffer, int size, unichar *result) From b9914abbf3a7fae6d15f26650a98d8e74aa1fa05 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 22 Mar 2016 16:54:34 +0100 Subject: [PATCH 054/140] Make use of terminal application keys configurable adds a new setting term_appkey_mode which can enable or disable the use of keyboard transmit (application keys) mode. Fixes #430 --- src/fe-text/gui-readline.c | 2 ++ src/fe-text/term.h | 1 + src/fe-text/terminfo-core.c | 23 +++++++++++++++++++---- src/fe-text/terminfo-core.h | 1 + 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index ff91f9e3..b93e5f0f 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -1060,6 +1060,7 @@ static void setup_changed(void) paste_join_multiline = settings_get_bool("paste_join_multiline"); paste_use_bracketed_mode = settings_get_bool("paste_use_bracketed_mode"); + term_set_appkey_mode(settings_get_bool("term_appkey_mode")); /* Enable the bracketed paste mode on demand */ term_set_bracketed_paste_mode(paste_use_bracketed_mode); } @@ -1082,6 +1083,7 @@ void gui_readline_init(void) g_get_current_time(&last_keypress); input_listen_init(STDIN_FILENO); + settings_add_bool("lookandfeel", "term_appkey_mode", TRUE); settings_add_str("history", "scroll_page_count", "/2"); settings_add_time("misc", "paste_detect_time", "5msecs"); settings_add_bool("misc", "paste_use_bracketed_mode", FALSE); diff --git a/src/fe-text/term.h b/src/fe-text/term.h index 5f0a799e..9b726d82 100644 --- a/src/fe-text/term.h +++ b/src/fe-text/term.h @@ -94,6 +94,7 @@ void term_refresh(TERM_WINDOW *window); void term_stop(void); +void term_set_appkey_mode(int enable); void term_set_bracketed_paste_mode(int enable); /* keyboard input handling */ diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c index aa833abf..15b00081 100644 --- a/src/fe-text/terminfo-core.c +++ b/src/fe-text/terminfo-core.c @@ -395,6 +395,12 @@ static void _ignore_parm(TERM_REC *term, int param) { } +static void terminfo_set_appkey_mode(TERM_REC *term, int set) +{ + if (term->TI_smkx && term->TI_rmkx) + tput(tparm(set ? term->TI_smkx : term->TI_rmkx)); +} + static void term_dec_set_bracketed_paste_mode(int enable) { if (enable) @@ -543,8 +549,8 @@ void terminfo_cont(TERM_REC *term) if (term->TI_smcup) tput(tparm(term->TI_smcup)); - if (term->TI_smkx) - tput(tparm(term->TI_smkx)); + if (term->appkey_enabled) + terminfo_set_appkey_mode(term, TRUE); if (term->bracketed_paste_enabled) term_dec_set_bracketed_paste_mode(TRUE); @@ -566,8 +572,8 @@ void terminfo_stop(TERM_REC *term) if (term->TI_rmcup) tput(tparm(term->TI_rmcup)); - if (term->TI_rmkx) - tput(tparm(term->TI_rmkx)); + if (term->appkey_enabled) + terminfo_set_appkey_mode(term, FALSE); /* reset input settings */ terminfo_input_deinit(term); @@ -695,6 +701,15 @@ static int term_setup(TERM_REC *term) return 1; } +void term_set_appkey_mode(int enable) +{ + if (current_term->appkey_enabled == enable) + return; + + current_term->appkey_enabled = enable; + terminfo_set_appkey_mode(current_term, enable); +} + void term_set_bracketed_paste_mode(int enable) { if (current_term->bracketed_paste_enabled == enable) diff --git a/src/fe-text/terminfo-core.h b/src/fe-text/terminfo-core.h index 0ef280a1..1253fd9d 100644 --- a/src/fe-text/terminfo-core.h +++ b/src/fe-text/terminfo-core.h @@ -94,6 +94,7 @@ struct _TERM_REC { const char *TI_rmkx; /* Terminal mode states */ + int appkey_enabled; int bracketed_paste_enabled; }; From aec2466e36ec32e97ec2eb8e1279e27a3d0fe0cb Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Mon, 21 Mar 2016 09:14:01 +0100 Subject: [PATCH 055/140] Improve cutbuffer handling * Adds two new keys which you can bind in /bind: yank_next_cutbuffer: Revert to the previous last deleted text append_next_kill: Append next deletion * Consecutive kills are now appended to the current cutbuffer --- src/fe-text/gui-entry.c | 171 ++++++++++++++++++++++++++----------- src/fe-text/gui-entry.h | 15 +++- src/fe-text/gui-readline.c | 62 ++++++++++++-- 3 files changed, 190 insertions(+), 58 deletions(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index f275c235..63dda34e 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -32,6 +32,8 @@ #undef i_tolower #undef i_isalnum +#define KILL_RING_MAX 10 + static unichar i_toupper(unichar c) { if (term_type == TERM_TYPE_UTF8) @@ -82,11 +84,22 @@ GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8) void gui_entry_destroy(GUI_ENTRY_REC *entry) { + GSList *tmp; + g_return_if_fail(entry != NULL); if (active_entry == entry) gui_entry_set_active(NULL); + for (tmp = entry->kill_ring; tmp != NULL; tmp = tmp->next) { + GUI_ENTRY_CUTBUFFER_REC *rec = tmp->data; + if (rec != NULL) { + g_free(rec->cutbuffer); + g_free(rec); + } + } + g_slist_free(entry->kill_ring); + g_free(entry->text); g_free(entry->prompt); g_free(entry); @@ -546,22 +559,42 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry) g_return_val_if_fail(entry != NULL, NULL); - if (entry->cutbuffer == NULL) + if (entry->kill_ring == NULL || entry->kill_ring->data == NULL) + return NULL; + + GUI_ENTRY_CUTBUFFER_REC *tmp = entry->kill_ring->data; + + if (tmp->cutbuffer == NULL) return NULL; if (entry->utf8) - buf = g_ucs4_to_utf8(entry->cutbuffer, -1, NULL, NULL, NULL); + buf = g_ucs4_to_utf8(tmp->cutbuffer, -1, NULL, NULL, NULL); else { - buf = g_malloc(entry->cutbuffer_len*6 + 1); + buf = g_malloc(tmp->cutbuffer_len*6 + 1); if (term_type == TERM_TYPE_BIG5) - unichars_to_big5(entry->cutbuffer, buf); + unichars_to_big5(tmp->cutbuffer, buf); else - for (i = 0; i <= entry->cutbuffer_len; i++) - buf[i] = entry->cutbuffer[i]; + for (i = 0; i <= tmp->cutbuffer_len; i++) + buf[i] = tmp->cutbuffer[i]; } return buf; } +char *gui_entry_get_next_cutbuffer(GUI_ENTRY_REC *entry) +{ + g_return_val_if_fail(entry != NULL, NULL); + + if (entry->kill_ring == NULL) + return NULL; + + GUI_ENTRY_CUTBUFFER_REC *tmp = entry->kill_ring->data; + + entry->kill_ring = g_slist_remove(entry->kill_ring, tmp); + entry->kill_ring = g_slist_append(entry->kill_ring, tmp); + + return gui_entry_get_cutbuffer(entry); +} + void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP update_cutbuffer) { int newpos, size = 0; @@ -573,6 +606,40 @@ void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP updat gui_entry_erase(entry, size, update_cutbuffer); } +static GUI_ENTRY_CUTBUFFER_REC *get_cutbuffer_rec(GUI_ENTRY_REC *entry, CUTBUFFER_UPDATE_OP update_cutbuffer) +{ + GUI_ENTRY_CUTBUFFER_REC *tmp = NULL; + + g_return_val_if_fail(entry != NULL, NULL); + + if (entry->kill_ring == NULL) { + /* no kill ring exists */ + entry->kill_ring = g_slist_prepend(entry->kill_ring, (void *)NULL); + } else { + tmp = entry->kill_ring->data; + + if (tmp != NULL && tmp->cutbuffer_len > 0 + && (!entry->previous_append_next_kill + || update_cutbuffer == CUTBUFFER_UPDATE_REPLACE)) { + /* a cutbuffer exists and should be replaced */ + entry->kill_ring = g_slist_prepend(entry->kill_ring, (void *)NULL); + } + } + + if (g_slist_length(entry->kill_ring) > KILL_RING_MAX) { + GUI_ENTRY_CUTBUFFER_REC *rec = g_slist_last(entry->kill_ring)->data; + entry->kill_ring = g_slist_remove(entry->kill_ring, rec); + if (rec != NULL) g_free(rec->cutbuffer); + g_free(rec); + } + + if (entry->kill_ring->data == NULL) { + entry->kill_ring->data = g_new0(GUI_ENTRY_CUTBUFFER_REC, 1); + } + + return entry->kill_ring->data; +} + void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_cutbuffer) { size_t w = 0; @@ -582,51 +649,59 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_ if (size == 0 || entry->pos < size) return; - if (update_cutbuffer != CUTBUFFER_UPDATE_NOOP - && entry->cutbuffer_len == 0) { - update_cutbuffer = CUTBUFFER_UPDATE_REPLACE; - } - int cutbuffer_new_size = entry->cutbuffer_len + size; - unichar *tmpcutbuffer = entry->cutbuffer; - switch (update_cutbuffer) { - case CUTBUFFER_UPDATE_APPEND: - entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); - memcpy(entry->cutbuffer, tmpcutbuffer, - entry->cutbuffer_len * sizeof(unichar)); - memcpy(entry->cutbuffer + entry->cutbuffer_len * sizeof(unichar), - entry->text + entry->pos - size, size * sizeof(unichar)); + if (update_cutbuffer != CUTBUFFER_UPDATE_NOOP) { + int cutbuffer_new_size; + unichar *tmpcutbuffer; + GUI_ENTRY_CUTBUFFER_REC *tmp = get_cutbuffer_rec(entry, update_cutbuffer); - entry->cutbuffer_len = cutbuffer_new_size; - entry->cutbuffer[cutbuffer_new_size] = '\0'; - g_free(tmpcutbuffer); - break; + if (tmp->cutbuffer_len == 0) { + update_cutbuffer = CUTBUFFER_UPDATE_REPLACE; + } - case CUTBUFFER_UPDATE_PREPEND: - entry->cutbuffer = g_new(unichar, cutbuffer_new_size+1); - memcpy(entry->cutbuffer, entry->text + entry->pos - size, - size * sizeof(unichar)); - memcpy(entry->cutbuffer + size, tmpcutbuffer, - entry->cutbuffer_len * sizeof(unichar)); + cutbuffer_new_size = tmp->cutbuffer_len + size; + tmpcutbuffer = tmp->cutbuffer; + entry->append_next_kill = TRUE; + switch (update_cutbuffer) { + case CUTBUFFER_UPDATE_APPEND: + tmp->cutbuffer = g_new(unichar, cutbuffer_new_size+1); + memcpy(tmp->cutbuffer, tmpcutbuffer, + tmp->cutbuffer_len * sizeof(unichar)); + memcpy(tmp->cutbuffer + tmp->cutbuffer_len * sizeof(unichar), + entry->text + entry->pos - size, size * sizeof(unichar)); - entry->cutbuffer_len = cutbuffer_new_size; - entry->cutbuffer[cutbuffer_new_size] = '\0'; - g_free(tmpcutbuffer); - break; + tmp->cutbuffer_len = cutbuffer_new_size; + tmp->cutbuffer[cutbuffer_new_size] = '\0'; + g_free(tmpcutbuffer); + break; - case CUTBUFFER_UPDATE_REPLACE: - /* put erased text to cutbuffer */ - if (entry->cutbuffer_len < size) { - g_free(entry->cutbuffer); - entry->cutbuffer = g_new(unichar, size+1); - } + case CUTBUFFER_UPDATE_PREPEND: + tmp->cutbuffer = g_new(unichar, cutbuffer_new_size+1); + memcpy(tmp->cutbuffer, entry->text + entry->pos - size, + size * sizeof(unichar)); + memcpy(tmp->cutbuffer + size, tmpcutbuffer, + tmp->cutbuffer_len * sizeof(unichar)); - entry->cutbuffer_len = size; - entry->cutbuffer[size] = '\0'; - memcpy(entry->cutbuffer, entry->text + entry->pos - size, size * sizeof(unichar)); - break; + tmp->cutbuffer_len = cutbuffer_new_size; + tmp->cutbuffer[cutbuffer_new_size] = '\0'; + g_free(tmpcutbuffer); + break; - case CUTBUFFER_UPDATE_NOOP: - break; + case CUTBUFFER_UPDATE_REPLACE: + /* put erased text to cutbuffer */ + if (tmp->cutbuffer_len < size) { + g_free(tmp->cutbuffer); + tmp->cutbuffer = g_new(unichar, size+1); + } + + tmp->cutbuffer_len = size; + tmp->cutbuffer[size] = '\0'; + memcpy(tmp->cutbuffer, entry->text + entry->pos - size, size * sizeof(unichar)); + break; + + case CUTBUFFER_UPDATE_NOOP: + /* cannot happen, handled in "if" */ + break; + } } if (entry->utf8) @@ -686,10 +761,10 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_O } if (to > 0) to++; - gui_entry_erase(entry, entry->pos-to, CUTBUFFER_UPDATE_REPLACE); + gui_entry_erase(entry, entry->pos-to, cutbuffer_op); } -void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space) +void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_OP cutbuffer_op) { int to, size; @@ -712,7 +787,7 @@ void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space) size = to-entry->pos; entry->pos = to; - gui_entry_erase(entry, size, CUTBUFFER_UPDATE_REPLACE); + gui_entry_erase(entry, size, cutbuffer_op); } void gui_entry_transpose_chars(GUI_ENTRY_REC *entry) diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h index d22a7fb8..8777f083 100644 --- a/src/fe-text/gui-entry.h +++ b/src/fe-text/gui-entry.h @@ -1,12 +1,16 @@ #ifndef __GUI_ENTRY_H #define __GUI_ENTRY_H +typedef struct { + int cutbuffer_len; + unichar *cutbuffer; +} GUI_ENTRY_CUTBUFFER_REC; + typedef struct { int text_len, text_alloc; /* as shorts, not chars */ unichar *text; - int cutbuffer_len; - unichar *cutbuffer; + GSList *kill_ring; /* all as shorts, not chars */ int xpos, ypos, width; /* entry position in screen */ @@ -18,6 +22,10 @@ typedef struct { int redraw_needed_from; unsigned int utf8:1; + + unsigned int previous_append_next_kill:1; + unsigned int append_next_kill:1; + unsigned int yank_preceded:1; } GUI_ENTRY_REC; typedef enum { @@ -47,11 +55,12 @@ void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str); void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr); char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry); +char *gui_entry_get_next_cutbuffer(GUI_ENTRY_REC *entry); void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP update_cutbuffer); void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_cutbuffer); void gui_entry_erase_cell(GUI_ENTRY_REC *entry); void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_OP cutbuffer_op); -void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space); +void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space, CUTBUFFER_UPDATE_OP cutbuffer_op); void gui_entry_transpose_chars(GUI_ENTRY_REC *entry); void gui_entry_transpose_words(GUI_ENTRY_REC *entry); diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index b93e5f0f..e0ffb4f1 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -73,6 +73,7 @@ static int paste_timeout_id; static int paste_use_bracketed_mode; static int paste_bracketed_mode; static int paste_was_bracketed_mode; +static int previous_yank_preceded; /* Terminal sequences that surround the input when the terminal has the * bracketed paste mode active. Fror more details see @@ -440,11 +441,20 @@ static void sig_gui_key_pressed(gpointer keyp) gui_entry_insert_char(active_entry, key); ret = 1; } else { + previous_yank_preceded = active_entry->yank_preceded; + active_entry->yank_preceded = FALSE; + active_entry->previous_append_next_kill = active_entry->append_next_kill; + active_entry->append_next_kill = FALSE; ret = key_pressed(keyboard, str); if (ret < 0) { /* key wasn't used for anything, print it */ gui_entry_insert_char(active_entry, key); } + if (ret == 0) { + /* combo not complete, ignore append_next_kill and yank_preceded */ + active_entry->append_next_kill = active_entry->previous_append_next_kill; + active_entry->yank_preceded = previous_yank_preceded; + } } /* ret = 0 : some key create multiple characters - we're in the middle @@ -571,7 +581,7 @@ static void key_erase_to_beg_of_line(void) int pos; pos = gui_entry_get_pos(active_entry); - gui_entry_erase(active_entry, pos, CUTBUFFER_UPDATE_REPLACE); + gui_entry_erase(active_entry, pos, CUTBUFFER_UPDATE_PREPEND); } static void key_erase_to_end_of_line(void) @@ -580,7 +590,7 @@ static void key_erase_to_end_of_line(void) pos = gui_entry_get_pos(active_entry); gui_entry_set_pos(active_entry, active_entry->text_len); - gui_entry_erase(active_entry, active_entry->text_len - pos, CUTBUFFER_UPDATE_REPLACE); + gui_entry_erase(active_entry, active_entry->text_len - pos, CUTBUFFER_UPDATE_APPEND); } static void key_yank_from_cutbuffer(void) @@ -590,7 +600,36 @@ static void key_yank_from_cutbuffer(void) cutbuffer = gui_entry_get_cutbuffer(active_entry); if (cutbuffer != NULL) { gui_entry_insert_text(active_entry, cutbuffer); - g_free(cutbuffer); + active_entry->yank_preceded = TRUE; + g_free(cutbuffer); + } +} + +static void key_yank_next_cutbuffer(void) +{ + GUI_ENTRY_CUTBUFFER_REC *rec; + guint length = 0; + char *cutbuffer; + + if (!previous_yank_preceded) { + if (settings_get_bool("bell_beeps")) { + signal_emit("beep", 0); + } + return; + } + + if (active_entry->kill_ring == NULL) + return; + + rec = active_entry->kill_ring->data; + if (rec != NULL) length = rec->cutbuffer_len; + + cutbuffer = gui_entry_get_next_cutbuffer(active_entry); + if (cutbuffer != NULL) { + gui_entry_erase(active_entry, length, CUTBUFFER_UPDATE_NOOP); + gui_entry_insert_text(active_entry, cutbuffer); + active_entry->yank_preceded = TRUE; + g_free(cutbuffer); } } @@ -632,22 +671,27 @@ static void key_backspace(void) static void key_delete_previous_word(void) { - gui_entry_erase_word(active_entry, FALSE, CUTBUFFER_UPDATE_REPLACE); + gui_entry_erase_word(active_entry, FALSE, CUTBUFFER_UPDATE_PREPEND); } static void key_delete_next_word(void) { - gui_entry_erase_next_word(active_entry, FALSE); + gui_entry_erase_next_word(active_entry, FALSE, CUTBUFFER_UPDATE_APPEND); } static void key_delete_to_previous_space(void) { - gui_entry_erase_word(active_entry, TRUE, CUTBUFFER_UPDATE_REPLACE); + gui_entry_erase_word(active_entry, TRUE, CUTBUFFER_UPDATE_PREPEND); } static void key_delete_to_next_space(void) { - gui_entry_erase_next_word(active_entry, TRUE); + gui_entry_erase_next_word(active_entry, TRUE, CUTBUFFER_UPDATE_APPEND); +} + +static void key_append_next_kill(void) +{ + active_entry->append_next_kill = TRUE; } static gboolean paste_timeout(gpointer data) @@ -1191,6 +1235,8 @@ void gui_readline_init(void) key_bind("erase_to_beg_of_line", "Erase everything before the cursor", NULL, NULL, (SIGNAL_FUNC) key_erase_to_beg_of_line); key_bind("erase_to_end_of_line", "Erase everything after the cursor", "^K", NULL, (SIGNAL_FUNC) key_erase_to_end_of_line); key_bind("yank_from_cutbuffer", "\"Undelete\", paste the last deleted text", "^Y", NULL, (SIGNAL_FUNC) key_yank_from_cutbuffer); + key_bind("yank_next_cutbuffer", "Revert to the previous last deleted text", NULL, NULL, (SIGNAL_FUNC) key_yank_next_cutbuffer); + key_bind("append_next_kill", "Append next deletion", NULL, NULL, (SIGNAL_FUNC) key_append_next_kill); key_bind("transpose_characters", "Swap current and previous character", "^T", NULL, (SIGNAL_FUNC) key_transpose_characters); key_bind("transpose_words", "Swap current and previous word", NULL, NULL, (SIGNAL_FUNC) key_transpose_words); key_bind("capitalize_word", "Capitalize the current word", NULL, NULL, (SIGNAL_FUNC) key_capitalize_word); @@ -1280,6 +1326,8 @@ void gui_readline_deinit(void) key_unbind("erase_to_beg_of_line", (SIGNAL_FUNC) key_erase_to_beg_of_line); key_unbind("erase_to_end_of_line", (SIGNAL_FUNC) key_erase_to_end_of_line); key_unbind("yank_from_cutbuffer", (SIGNAL_FUNC) key_yank_from_cutbuffer); + key_unbind("yank_next_cutbuffer", (SIGNAL_FUNC) key_yank_next_cutbuffer); + key_unbind("append_next_kill", (SIGNAL_FUNC) key_append_next_kill); key_unbind("transpose_characters", (SIGNAL_FUNC) key_transpose_characters); key_unbind("transpose_words", (SIGNAL_FUNC) key_transpose_words); From ec4ecd844bbc9c3254963862b0fff6be290db4ad Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Thu, 24 Mar 2016 16:01:07 +0100 Subject: [PATCH 056/140] Revert "Removed the obsolete SQUERY and SERVLIST commands" This reverts commit 4beebe3238dda96efd4c3a0a6f6002ad5afc96e7. --- docs/help/in/list.in | 6 +++--- docs/help/in/servlist.in | 23 +++++++++++++++++++++++ docs/help/in/squery.in | 16 ++++++++++++++++ src/irc/core/irc-commands.c | 6 ++++++ 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 docs/help/in/servlist.in create mode 100644 docs/help/in/squery.in diff --git a/docs/help/in/list.in b/docs/help/in/list.in index 33f05e8b..b796eed0 100644 --- a/docs/help/in/list.in +++ b/docs/help/in/list.in @@ -25,10 +25,10 @@ %9Remarks:%9 Not all networks support server-side filtering and may provide a network - service instead; on IRCnet, you may use the ALIS service: + service or service bot instead; on IRCnet, you may use the List service: - /QUOTE SQUERY ALIS :HELP + /SQUERY List HELP /MSG ALIS HELP -%9See also:%9 QUOTE, STATS, WHOIS +%9See also:%9 STATS, SQUERY, WHOIS diff --git a/docs/help/in/servlist.in b/docs/help/in/servlist.in new file mode 100644 index 00000000..0a0d025f --- /dev/null +++ b/docs/help/in/servlist.in @@ -0,0 +1,23 @@ + +%9Syntax:%9 + +@SYNTAX:servlist@ + +%9Parameters:%9 + + limits the output to the services which names matches + the mask. + limits the output to the services of the specified type. + +%9Description:%9 + + List the network services currently present on the + IRC network. + +%9Examples:%9 + + /SERVLIST *@javairc.* + /SERVLIST * 0xD000 + +%9See also:%9 SQUERY + diff --git a/docs/help/in/squery.in b/docs/help/in/squery.in new file mode 100644 index 00000000..59ee8008 --- /dev/null +++ b/docs/help/in/squery.in @@ -0,0 +1,16 @@ + +%9Syntax:%9 + +@SYNTAX:squery@ + +%9Parameters:%9 + + - Service nickname or full hostmask of service to query. + - Message to send to the service. + +%9Description:%9 + + /SQUERY sends a query to the specified service. + +%9See also:%9 SERVLIST, LIST, MSG + diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index 6baf2f6d..32ee8845 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -1018,11 +1018,15 @@ void irc_commands_init(void) command_bind_irc("trace", NULL, (SIGNAL_FUNC) command_self); /* SYNTAX: VERSION [|] */ command_bind_irc("version", NULL, (SIGNAL_FUNC) command_self); + /* SYNTAX: SERVLIST [ []] */ + command_bind_irc("servlist", NULL, (SIGNAL_FUNC) command_self); /* SYNTAX: SILENCE [[+|-]] SILENCE [] */ command_bind_irc("silence", NULL, (SIGNAL_FUNC) command_self); command_bind_irc("unsilence", NULL, (SIGNAL_FUNC) cmd_unsilence); command_bind_irc("sconnect", NULL, (SIGNAL_FUNC) cmd_sconnect); + /* SYNTAX: SQUERY [] */ + command_bind_irc("squery", NULL, (SIGNAL_FUNC) command_2self); /* SYNTAX: DIE */ command_bind_irc("die", NULL, (SIGNAL_FUNC) command_self); /* SYNTAX: HASH */ @@ -1091,9 +1095,11 @@ void irc_commands_deinit(void) command_unbind("time", (SIGNAL_FUNC) command_self); command_unbind("trace", (SIGNAL_FUNC) command_self); command_unbind("version", (SIGNAL_FUNC) command_self); + command_unbind("servlist", (SIGNAL_FUNC) command_self); command_unbind("silence", (SIGNAL_FUNC) command_self); command_unbind("unsilence", (SIGNAL_FUNC) cmd_unsilence); command_unbind("sconnect", (SIGNAL_FUNC) cmd_sconnect); + command_unbind("squery", (SIGNAL_FUNC) command_2self); command_unbind("die", (SIGNAL_FUNC) command_self); command_unbind("hash", (SIGNAL_FUNC) command_self); command_unbind("oper", (SIGNAL_FUNC) cmd_oper); From 2ba4b9d26afb87c2e661b1c07313ca78b3c5618e Mon Sep 17 00:00:00 2001 From: dequis Date: Mon, 4 Apr 2016 03:47:48 -0300 Subject: [PATCH 057/140] net_gethosterror: Handle EAI_SYSTEM ("System error") properly That error code means "check errno". A few users got it and we never figured out what happened - it usually fixed itself after restarting something - so hopefully with this we'll have more information the next time. --- src/core/network.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/network.c b/src/core/network.c index 76659f3e..3e1b7c70 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -510,7 +510,11 @@ const char *net_gethosterror(int error) { g_return_val_if_fail(error != 0, NULL); - return gai_strerror(error); + if (error == EAI_SYSTEM) { + return strerror(errno); + } else { + return gai_strerror(error); + } } /* return TRUE if host lookup failed because it didn't exist (ie. not From 9fa3869a97be7b79c0aa5f7a7e80d655b0a7f8d8 Mon Sep 17 00:00:00 2001 From: B Thibault Date: Fri, 29 Apr 2016 00:12:28 +0200 Subject: [PATCH 058/140] retab --- src/fe-common/core/hilight-text.c | 120 +++++++++++++++--------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index b746f636..6aa19b88 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -49,7 +49,7 @@ static void reset_level_cache(void) HILIGHT_REC *rec = tmp->data; if (never_hilight_level & rec->level) - never_hilight_level &= ~rec->level; + never_hilight_level &= ~rec->level; } } @@ -68,17 +68,17 @@ static void hilight_add_config(HILIGHT_REC *rec) node = iconfig_node_traverse("(hilights", TRUE); node = iconfig_node_section(node, NULL, NODE_TYPE_BLOCK); - iconfig_node_set_str(node, "text", rec->text); - if (rec->level > 0) iconfig_node_set_int(node, "level", rec->level); - if (rec->color) iconfig_node_set_str(node, "color", rec->color); - if (rec->act_color) iconfig_node_set_str(node, "act_color", rec->act_color); - if (rec->priority > 0) iconfig_node_set_int(node, "priority", rec->priority); - iconfig_node_set_bool(node, "nick", rec->nick); - iconfig_node_set_bool(node, "word", rec->word); - if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE); - if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE); - if (rec->regexp) iconfig_node_set_bool(node, "regexp", TRUE); - if (rec->servertag) iconfig_node_set_str(node, "servertag", rec->servertag); + iconfig_node_set_str(node, "text", rec->text); + if (rec->level > 0) iconfig_node_set_int(node, "level", rec->level); + if (rec->color) iconfig_node_set_str(node, "color", rec->color); + if (rec->act_color) iconfig_node_set_str(node, "act_color", rec->act_color); + if (rec->priority > 0) iconfig_node_set_int(node, "priority", rec->priority); + iconfig_node_set_bool(node, "nick", rec->nick); + iconfig_node_set_bool(node, "word", rec->word); + if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE); + if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE); + if (rec->regexp) iconfig_node_set_bool(node, "regexp", TRUE); + if (rec->servertag) iconfig_node_set_str(node, "servertag", rec->servertag); if (rec->channels != NULL && *rec->channels != NULL) { node = iconfig_node_section(node, "channels", NODE_TYPE_LIST); @@ -191,7 +191,7 @@ static HILIGHT_REC *hilight_find(const char *text, char **channels) } static int hilight_match_text(HILIGHT_REC *rec, const char *text, - int *match_beg, int *match_end) + int *match_beg, int *match_end) { char *match; @@ -200,9 +200,9 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text, regmatch_t rmatch[1]; if (rec->regexp_compiled && - regexec(&rec->preg, text, 1, rmatch, 0) == 0) { + regexec(&rec->preg, text, 1, rmatch, 0) == 0) { if (rmatch[0].rm_so > 0 && - match_beg != NULL && match_end != NULL) { + match_beg != NULL && match_end != NULL) { *match_beg = rmatch[0].rm_so; *match_end = rmatch[0].rm_eo; } @@ -222,7 +222,7 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text, } } - return FALSE; + return FALSE; } #define hilight_match_level(rec, level) \ @@ -267,14 +267,14 @@ HILIGHT_REC *hilight_match(SERVER_REC *server, const char *channel, HILIGHT_REC *rec = tmp->data; if (!rec->nickmask && hilight_match_level(rec, level) && - hilight_match_channel(rec, channel) && - (rec->servertag == NULL || - (server != NULL && g_ascii_strcasecmp(rec->servertag, server->tag) == 0)) && - hilight_match_text(rec, str, match_beg, match_end)) + hilight_match_channel(rec, channel) && + (rec->servertag == NULL || + (server != NULL && g_ascii_strcasecmp(rec->servertag, server->tag) == 0)) && + hilight_match_text(rec, str, match_beg, match_end)) return rec; } - return NULL; + return NULL; } static char *hilight_get_act_color(HILIGHT_REC *rec) @@ -308,7 +308,7 @@ void hilight_update_text_dest(TEXT_DEST_REC *dest, HILIGHT_REC *rec) g_free_and_null(dest->hilight_color); if (rec->act_color != NULL && g_strcmp0(rec->act_color, "%n") == 0) dest->level |= MSGLEVEL_NO_ACT; - else + else dest->hilight_color = hilight_get_act_color(rec); } @@ -362,29 +362,29 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text, /* hilight whole line */ char *tmp = strip_codes(text); newstr = g_strconcat(color, tmp, NULL); - g_free(tmp); + g_free(tmp); } else { /* hilight part of the line */ - GString *tmp; - char *middle; + GString *tmp; + char *middle; int pos, color_pos, color_len; - tmp = g_string_new(NULL); + tmp = g_string_new(NULL); - /* start of the line */ + /* start of the line */ pos = strip_real_length(text, hilight_start, NULL, NULL); g_string_append(tmp, text); - g_string_truncate(tmp, pos); + g_string_truncate(tmp, pos); /* color */ - g_string_append(tmp, color); + g_string_append(tmp, color); /* middle of the line, stripped */ middle = strip_codes(text+pos); - pos = tmp->len; + pos = tmp->len; g_string_append(tmp, middle); - g_string_truncate(tmp, pos+hilight_len); - g_free(middle); + g_string_truncate(tmp, pos+hilight_len); + g_free(middle); /* end of the line */ pos = strip_real_length(text, hilight_end, @@ -398,8 +398,8 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text, } g_string_append(tmp, text+pos); - newstr = tmp->str; - g_string_free(tmp, FALSE); + newstr = tmp->str; + g_string_free(tmp, FALSE); } signal_emit("print text", 3, dest, newstr, stripped); @@ -417,7 +417,7 @@ HILIGHT_REC *hilight_match_nick(SERVER_REC *server, const char *channel, HILIGHT_REC *rec; rec = hilight_match(server, channel, nick, address, - level, msg, NULL, NULL); + level, msg, NULL, NULL); return (rec == NULL || !rec->nick) ? NULL : rec; } @@ -475,7 +475,7 @@ static void read_hilight_config(void) if (node != NULL) rec->channels = config_node_get_list(node); } - reset_cache(); + reset_cache(); } static void hilight_print(int index, HILIGHT_REC *rec) @@ -519,10 +519,10 @@ static void hilight_print(int index, HILIGHT_REC *rec) if (levelstr != NULL) levelstr = g_strconcat(levelstr, " ", NULL); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, - TXT_HILIGHT_LINE, index, rec->text, - chans != NULL ? chans : "", - levelstr != NULL ? levelstr : "", - options->str); + TXT_HILIGHT_LINE, index, rec->text, + chans != NULL ? chans : "", + levelstr != NULL ? levelstr : "", + options->str); g_free_not_null(chans); g_free_not_null(levelstr); g_string_free(options, TRUE); @@ -548,7 +548,7 @@ static void cmd_hilight_show(void) [-network ] [-channels ] */ static void cmd_hilight(const char *data) { - GHashTable *optlist; + GHashTable *optlist; HILIGHT_REC *rec; char *colorarg, *actcolorarg, *levelarg, *priorityarg, *chanarg, *text, *servertag; char **channels; @@ -562,7 +562,7 @@ static void cmd_hilight(const char *data) } if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | - PARAM_FLAG_GETREST, "hilight", &optlist, &text)) + PARAM_FLAG_GETREST, "hilight", &optlist, &text)) return; chanarg = g_hash_table_lookup(optlist, "channels"); @@ -582,7 +582,7 @@ static void cmd_hilight(const char *data) rec = g_new0(HILIGHT_REC, 1); /* default to nick/word hilighting */ - rec->nick = TRUE; + rec->nick = TRUE; rec->word = TRUE; rec->text = g_strdup(text); @@ -602,11 +602,11 @@ static void cmd_hilight(const char *data) if (g_hash_table_lookup(optlist, "word") != NULL) { rec->word = TRUE; - rec->nick = FALSE; + rec->nick = FALSE; } if (g_hash_table_lookup(optlist, "nick") != NULL) - rec->nick = TRUE; + rec->nick = TRUE; rec->nickmask = g_hash_table_lookup(optlist, "mask") != NULL; rec->fullword = g_hash_table_lookup(optlist, "full") != NULL; @@ -631,7 +631,7 @@ static void cmd_hilight(const char *data) hilight_create(rec); hilight_print(g_slist_index(hilights, rec)+1, rec); - cmd_params_free(free_arg); + cmd_params_free(free_arg); reset_cache(); } @@ -649,7 +649,7 @@ static void cmd_dehilight(const char *data) } else { /* with mask */ char *chans[2] = { "*", NULL }; - rec = hilight_find(data, chans); + rec = hilight_find(data, chans); } if (rec == NULL) @@ -657,20 +657,20 @@ static void cmd_dehilight(const char *data) else { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_HILIGHT_REMOVED, rec->text); hilight_remove(rec); - reset_cache(); + reset_cache(); } } static void hilight_nick_cache(GHashTable *list, CHANNEL_REC *channel, - NICK_REC *nick) + NICK_REC *nick) { GSList *tmp; HILIGHT_REC *match; - char *nickmask; + char *nickmask; int len, best_match; if (nick->host == NULL) - return; /* don't check until host is known */ + return; /* don't check until host is known */ nickmask = g_strconcat(nick->nick, "!", nick->host, NULL); @@ -679,8 +679,8 @@ static void hilight_nick_cache(GHashTable *list, CHANNEL_REC *channel, HILIGHT_REC *rec = tmp->data; if (rec->nickmask && - hilight_match_channel(rec, channel->name) && - match_wildcards(rec->text, nickmask)) { + hilight_match_channel(rec, channel->name) && + match_wildcards(rec->text, nickmask)) { len = strlen(rec->text); if (best_match < len) { best_match = len; @@ -691,7 +691,7 @@ static void hilight_nick_cache(GHashTable *list, CHANNEL_REC *channel, g_free_not_null(nickmask); if (match != NULL) - g_hash_table_insert(list, nick, match); + g_hash_table_insert(list, nick, match); } static void read_settings(void) @@ -706,14 +706,14 @@ void hilight_text_init(void) settings_add_str("lookandfeel", "hilight_act_color", "%M"); settings_add_level("lookandfeel", "hilight_level", "PUBLIC DCCMSGS"); - read_settings(); + read_settings(); nickmatch = nickmatch_init(hilight_nick_cache); read_hilight_config(); signal_add_first("print text", (SIGNAL_FUNC) sig_print_text); - signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config); - signal_add("setup changed", (SIGNAL_FUNC) read_settings); + signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config); + signal_add("setup changed", (SIGNAL_FUNC) read_settings); command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight); command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight); @@ -723,11 +723,11 @@ void hilight_text_init(void) void hilight_text_deinit(void) { hilights_destroy_all(); - nickmatch_deinit(nickmatch); + nickmatch_deinit(nickmatch); signal_remove("print text", (SIGNAL_FUNC) sig_print_text); - signal_remove("setup reread", (SIGNAL_FUNC) read_hilight_config); - signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + signal_remove("setup reread", (SIGNAL_FUNC) read_hilight_config); + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); command_unbind("hilight", (SIGNAL_FUNC) cmd_hilight); command_unbind("dehilight", (SIGNAL_FUNC) cmd_dehilight); From d8a6e666994ec4265459ed1e6665c01eb651eb82 Mon Sep 17 00:00:00 2001 From: B Thibault Date: Fri, 29 Apr 2016 01:01:34 +0200 Subject: [PATCH 059/140] Ref #421 (Add an option to make /hilight case sensitive) Allow use of /hilight -case exAMPle (compatible with other options) Added matchcase to hilight config file (exemple: { text = exAMPle; matchcase = yes; } ) --- docs/help/in/hilight.in | 1 + src/fe-common/core/hilight-text.c | 21 ++++++++++++++++----- src/fe-common/core/hilight-text.h | 1 + 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/help/in/hilight.in b/docs/help/in/hilight.in index fabbc2ea..677e64c3 100644 --- a/docs/help/in/hilight.in +++ b/docs/help/in/hilight.in @@ -10,6 +10,7 @@ -line: Highlights the whole line. -mask: Highlights all messages from users matching the mask. -full: The text must match the full word. + -case: The text must match case. -regexp: The text is a regular expression. -color: The color the display the highlight in. -actcolor: The color to mark the highlight activity in the statusbar. diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 6aa19b88..13c7c64d 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -78,6 +78,7 @@ static void hilight_add_config(HILIGHT_REC *rec) if (rec->nickmask) iconfig_node_set_bool(node, "mask", TRUE); if (rec->fullword) iconfig_node_set_bool(node, "fullword", TRUE); if (rec->regexp) iconfig_node_set_bool(node, "regexp", TRUE); + if (rec->case_sensitive) iconfig_node_set_bool(node, "matchcase", TRUE); if (rec->servertag) iconfig_node_set_str(node, "servertag", rec->servertag); if (rec->channels != NULL && *rec->channels != NULL) { @@ -210,9 +211,16 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text, } #endif } else { - match = rec->fullword ? - stristr_full(text, rec->text) : - stristr(text, rec->text); + if (rec->case_sensitive) { + match = rec->fullword ? + strstr_full(text, rec->text) : + strstr(text, rec->text); + } + else { + match = rec->fullword ? + stristr_full(text, rec->text) : + stristr(text, rec->text); + } if (match != NULL) { if (match_beg != NULL && match_end != NULL) { *match_beg = (int) (match-text); @@ -464,6 +472,7 @@ static void read_hilight_config(void) rec->priority = config_node_get_int(node, "priority", 0); rec->nick = config_node_get_bool(node, "nick", TRUE); rec->word = config_node_get_bool(node, "word", TRUE); + rec->case_sensitive = config_node_get_bool(node, "matchcase", FALSE); rec->nickmask = config_node_get_bool(node, "mask", FALSE); rec->fullword = config_node_get_bool(node, "fullword", FALSE); @@ -495,6 +504,7 @@ static void hilight_print(int index, HILIGHT_REC *rec) if (rec->nickmask) g_string_append(options, "-mask "); if (rec->fullword) g_string_append(options, "-full "); + if (rec->case_sensitive) g_string_append(options, "-case "); if (rec->regexp) { g_string_append(options, "-regexp "); #ifdef HAVE_REGEX_H @@ -543,7 +553,7 @@ static void cmd_hilight_show(void) printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_HILIGHT_FOOTER); } -/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -regexp] +/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -case | -regexp] [-color ] [-actcolor ] [-level ] [-network ] [-channels ] */ static void cmd_hilight(const char *data) @@ -611,6 +621,7 @@ static void cmd_hilight(const char *data) rec->nickmask = g_hash_table_lookup(optlist, "mask") != NULL; rec->fullword = g_hash_table_lookup(optlist, "full") != NULL; rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL; + rec->case_sensitive = g_hash_table_lookup(optlist, "case") != NULL; if (colorarg != NULL) { g_free_and_null(rec->color); @@ -717,7 +728,7 @@ void hilight_text_init(void) command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight); command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight); - command_set_options("hilight", "-color -actcolor -level -priority -network -channels nick word line mask full regexp"); + command_set_options("hilight", "-color -actcolor -level -priority -network -channels nick word line mask full regexp case"); } void hilight_text_deinit(void) diff --git a/src/fe-common/core/hilight-text.h b/src/fe-common/core/hilight-text.h index 3c897def..ae05e1ca 100644 --- a/src/fe-common/core/hilight-text.h +++ b/src/fe-common/core/hilight-text.h @@ -23,6 +23,7 @@ struct _HILIGHT_REC { unsigned int nickmask:1; /* `text' is a nick mask */ unsigned int fullword:1; /* match `text' only for full words */ unsigned int regexp:1; /* `text' is a regular expression */ + unsigned int case_sensitive:1;/* `text' must match case */ #ifdef HAVE_REGEX_H unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ regex_t preg; From ddd54164304e8d4bc3b709dbe6d2eca7832cff81 Mon Sep 17 00:00:00 2001 From: B Thibault Date: Fri, 29 Apr 2016 11:00:34 +0200 Subject: [PATCH 060/140] changed command-line -case to -matchcase --- docs/help/in/hilight.in | 2 +- src/fe-common/core/hilight-text.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/help/in/hilight.in b/docs/help/in/hilight.in index 677e64c3..2f396430 100644 --- a/docs/help/in/hilight.in +++ b/docs/help/in/hilight.in @@ -10,7 +10,7 @@ -line: Highlights the whole line. -mask: Highlights all messages from users matching the mask. -full: The text must match the full word. - -case: The text must match case. + -matchcase: The text must match case. -regexp: The text is a regular expression. -color: The color the display the highlight in. -actcolor: The color to mark the highlight activity in the statusbar. diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 13c7c64d..78815a42 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -504,7 +504,7 @@ static void hilight_print(int index, HILIGHT_REC *rec) if (rec->nickmask) g_string_append(options, "-mask "); if (rec->fullword) g_string_append(options, "-full "); - if (rec->case_sensitive) g_string_append(options, "-case "); + if (rec->case_sensitive) g_string_append(options, "-matchcase "); if (rec->regexp) { g_string_append(options, "-regexp "); #ifdef HAVE_REGEX_H @@ -553,7 +553,7 @@ static void cmd_hilight_show(void) printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_HILIGHT_FOOTER); } -/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -case | -regexp] +/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -matchcase | -regexp] [-color ] [-actcolor ] [-level ] [-network ] [-channels ] */ static void cmd_hilight(const char *data) @@ -621,7 +621,7 @@ static void cmd_hilight(const char *data) rec->nickmask = g_hash_table_lookup(optlist, "mask") != NULL; rec->fullword = g_hash_table_lookup(optlist, "full") != NULL; rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL; - rec->case_sensitive = g_hash_table_lookup(optlist, "case") != NULL; + rec->case_sensitive = g_hash_table_lookup(optlist, "matchcase") != NULL; if (colorarg != NULL) { g_free_and_null(rec->color); @@ -728,7 +728,7 @@ void hilight_text_init(void) command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight); command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight); - command_set_options("hilight", "-color -actcolor -level -priority -network -channels nick word line mask full regexp case"); + command_set_options("hilight", "-color -actcolor -level -priority -network -channels nick word line mask full regexp matchcase"); } void hilight_text_deinit(void) From e7a18759ecb02a0b1fcbb118b9e732e604268afd Mon Sep 17 00:00:00 2001 From: isundil Date: Fri, 29 Apr 2016 22:17:48 +0000 Subject: [PATCH 061/140] Added case-sensitive regexp matching for hilights --- src/fe-common/core/hilight-text.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 78815a42..d1c4718c 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -122,8 +122,11 @@ static void hilight_init_rec(HILIGHT_REC *rec) { #ifdef HAVE_REGEX_H if (rec->regexp_compiled) regfree(&rec->preg); - rec->regexp_compiled = !rec->regexp ? FALSE : - regcomp(&rec->preg, rec->text, REG_EXTENDED|REG_ICASE) == 0; + if (!rec->regexp) + rec->regexp_compiled = FALSE; + else + rec->regexp_compiled = regcomp(&rec->preg, rec->text, + rec->case_sensitive ? REG_EXTENDED : (REG_EXTENDED|REG_ICASE)) == 0; #endif } From b24921db7a49d01ce30245999483589bcea47d53 Mon Sep 17 00:00:00 2001 From: dennisschagt Date: Sat, 30 Apr 2016 09:44:26 +0200 Subject: [PATCH 062/140] Correct error/typo "You"->"Your" in help message --- docs/help/in/away.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/help/in/away.in b/docs/help/in/away.in index e0cf3685..75bc46c4 100644 --- a/docs/help/in/away.in +++ b/docs/help/in/away.in @@ -8,8 +8,8 @@ -one: Marks yourself as away on the active server. -all: Marks yourself as away on all the servers you are connected to. - You away message; if no argument is given, your away status will be removed. - + Your away message; if no argument is given, your away status will be removed. + %9Description:%9 Marks yourself as 'away'; this method is used to inform people that you From b63339af89abc9830ecf8c56916db9eb1a42e005 Mon Sep 17 00:00:00 2001 From: isundil Date: Sat, 30 Apr 2016 18:26:26 +0000 Subject: [PATCH 063/140] Increased ABI version --- src/common.h | 2 +- src/fe-common/core/hilight-text.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/common.h b/src/common.h index 33dbd481..4fd6d331 100644 --- a/src/common.h +++ b/src/common.h @@ -6,7 +6,7 @@ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ -#define IRSSI_ABI_VERSION 3 +#define IRSSI_ABI_VERSION 4 #define DEFAULT_SERVER_ADD_PORT 6667 diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index d1c4718c..36e1e78c 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -218,8 +218,7 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text, match = rec->fullword ? strstr_full(text, rec->text) : strstr(text, rec->text); - } - else { + } else { match = rec->fullword ? stristr_full(text, rec->text) : stristr(text, rec->text); From 47e792da05f79c624a190fd5780e07f171fd7bd1 Mon Sep 17 00:00:00 2001 From: pisculichi Date: Mon, 2 May 2016 16:01:48 +0000 Subject: [PATCH 064/140] Fix some ANSI C issues. --- src/fe-common/core/fe-messages.c | 5 +++-- src/fe-common/core/themes.c | 2 +- src/fe-text/gui-entry.c | 9 ++++++--- src/fe-text/gui-readline.c | 3 ++- src/fe-text/statusbar.c | 2 +- src/irc/proxy/proxy.c | 3 ++- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index 3240fd10..bc2a30d6 100644 --- a/src/fe-common/core/fe-messages.c +++ b/src/fe-common/core/fe-messages.c @@ -175,6 +175,7 @@ static void sig_message_public(SERVER_REC *server, const char *msg, int for_me, print_channel, level; char *nickmode, *color, *freemsg = NULL; HILIGHT_REC *hilight; + TEXT_DEST_REC dest; /* NOTE: this may return NULL if some channel is just closed with /WINDOW CLOSE and server still sends the few last messages */ @@ -214,7 +215,6 @@ static void sig_message_public(SERVER_REC *server, const char *msg, if (printnick == NULL) printnick = nick; - TEXT_DEST_REC dest; format_create_dest(&dest, server, target, level, NULL); dest.address = address; dest.nick = nick; @@ -396,8 +396,9 @@ static void sig_message_quit(SERVER_REC *server, const char *nick, count = 0; windows = NULL; chans = g_string_new(NULL); for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *rec; level = MSGLEVEL_QUITS; - CHANNEL_REC *rec = tmp->data; + rec = tmp->data; if (!nicklist_find(rec, nick)) continue; diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c index 58e7b557..2b1459be 100644 --- a/src/fe-common/core/themes.c +++ b/src/fe-common/core/themes.c @@ -365,9 +365,9 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format) GString *str; char *ret; theme_rm_col dummy, reset; + int braces = 1; /* we start with one brace opened */ dummy.m[0] = '\0'; strcpy(reset.m, "n"); - int braces = 1; /* we start with one brace opened */ str = g_string_new(NULL); while (**format != '\0' && braces != 0) { diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 63dda34e..31fe0e1e 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -554,6 +554,7 @@ void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr) char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry) { + GUI_ENTRY_CUTBUFFER_REC *tmp; char *buf; int i; @@ -562,7 +563,7 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry) if (entry->kill_ring == NULL || entry->kill_ring->data == NULL) return NULL; - GUI_ENTRY_CUTBUFFER_REC *tmp = entry->kill_ring->data; + tmp = entry->kill_ring->data; if (tmp->cutbuffer == NULL) return NULL; @@ -582,12 +583,14 @@ char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry) char *gui_entry_get_next_cutbuffer(GUI_ENTRY_REC *entry) { + GUI_ENTRY_CUTBUFFER_REC *tmp; + g_return_val_if_fail(entry != NULL, NULL); if (entry->kill_ring == NULL) return NULL; - GUI_ENTRY_CUTBUFFER_REC *tmp = entry->kill_ring->data; + tmp = entry->kill_ring->data; entry->kill_ring = g_slist_remove(entry->kill_ring, tmp); entry->kill_ring = g_slist_append(entry->kill_ring, tmp); @@ -608,7 +611,7 @@ void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, CUTBUFFER_UPDATE_OP updat static GUI_ENTRY_CUTBUFFER_REC *get_cutbuffer_rec(GUI_ENTRY_REC *entry, CUTBUFFER_UPDATE_OP update_cutbuffer) { - GUI_ENTRY_CUTBUFFER_REC *tmp = NULL; + GUI_ENTRY_CUTBUFFER_REC *tmp; g_return_val_if_fail(entry != NULL, NULL); diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index e0ffb4f1..7c71edd7 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -696,10 +696,11 @@ static void key_append_next_kill(void) static gboolean paste_timeout(gpointer data) { + int split_lines; paste_was_bracketed_mode = paste_bracketed_mode; /* number of lines after splitting extra-long messages */ - int split_lines = paste_buffer->len / LINE_SPLIT_LIMIT; + split_lines = paste_buffer->len / LINE_SPLIT_LIMIT; /* Take into account the fact that a line may be split every LINE_SPLIT_LIMIT characters */ if (paste_line_count == 0 && split_lines <= paste_verify_line_count) { diff --git a/src/fe-text/statusbar.c b/src/fe-text/statusbar.c index 5448243a..f0dff828 100644 --- a/src/fe-text/statusbar.c +++ b/src/fe-text/statusbar.c @@ -671,8 +671,8 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only, WI_ITEM_REC *wiitem; char *tmpstr, *tmpstr2; theme_rm_col reset; - strcpy(reset.m, "n"); int len; + strcpy(reset.m, "n"); if (str == NULL) str = statusbar_item_get_value(item); diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c index 1a714045..2875d2c2 100644 --- a/src/irc/proxy/proxy.c +++ b/src/irc/proxy/proxy.c @@ -28,13 +28,14 @@ /* SYNTAX: IRSSIPROXY STATUS */ static void cmd_irssiproxy_status(const char *data, IRC_SERVER_REC *server) { + GSList *tmp; + if (!settings_get_bool("irssiproxy")) { printtext(server, NULL, MSGLEVEL_CLIENTNOTICE, "Proxy is currently disabled"); return; } - GSList *tmp; printtext(server, NULL, MSGLEVEL_CLIENTNOTICE, "Proxy: Currently connected clients: %d", From 3376d324e1e174e2885efbb7f1f056bc2a0d2857 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Mon, 9 May 2016 16:55:35 +0200 Subject: [PATCH 065/140] improve perl @INC detection --- acconfig.h | 30 --------------------- configure.ac | 74 ++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 46 deletions(-) delete mode 100644 acconfig.h diff --git a/acconfig.h b/acconfig.h deleted file mode 100644 index 53e268d7..00000000 --- a/acconfig.h +++ /dev/null @@ -1,30 +0,0 @@ -/* misc.. */ -#undef HAVE_SOCKS_H -#undef HAVE_STATIC_PERL -#undef HAVE_GMODULE - -/* macros/curses checks */ -#undef HAS_CURSES -#undef USE_SUNOS_CURSES -#undef USE_BSD_CURSES -#undef USE_SYSV_CURSES -#undef USE_NCURSES -#undef NO_COLOR_CURSES -#undef SCO_FLAVOR - -/* our own curses checks */ -#undef HAVE_NCURSES_USE_DEFAULT_COLORS -#undef HAVE_CURSES_IDCOK -#undef HAVE_CURSES_RESIZETERM -#undef HAVE_CURSES_WRESIZE - -/* terminfo/termcap */ -#undef HAVE_TERMINFO - -/* What type should be used for uoff_t */ -#undef UOFF_T_INT -#undef UOFF_T_LONG -#undef UOFF_T_LONG_LONG - -/* printf()-format for uoff_t, eg. "u" or "lu" or "llu" */ -#undef PRIuUOFF_T diff --git a/configure.ac b/configure.ac index 2c47bd2b..0e5f2f0d 100644 --- a/configure.ac +++ b/configure.ac @@ -79,7 +79,6 @@ AC_ARG_WITH(modules, if test "x$prefix" != "xNONE"; then prefix=`eval echo $prefix` PERL_MM_PARAMS="INSTALLDIRS=perl INSTALL_BASE=$prefix" - perl_library_dir="PERL_USE_LIB" perl_set_use_lib=yes perl_prefix_note=yes @@ -97,30 +96,35 @@ AC_ARG_WITH(perl-staticlib, AC_ARG_WITH(perl-lib, -[ --with-perl-lib=[site|vendor|DIR] Specify where to install the +[ --with-perl-lib=[perl|site|vendor|DIR] Specify where to install the Perl libraries for irssi, default is site], if test "x$withval" = xyes; then want_perl=yes elif test "x$withval" = xno; then want_perl=no + elif test "x$withval" = xperl; then + want_perl=yes + perl_prefix_note=no + PERL_MM_PARAMS="INSTALLDIRS=perl" + perl_set_use_lib=no elif test "x$withval" = xsite; then want_perl=yes perl_prefix_note=no PERL_MM_PARAMS="" + perl_set_use_lib=no elif test "x$withval" = xvendor; then want_perl=yes perl_prefix_note=no if test -z "`$perlpath -v|grep '5\.0'`"; then PERL_MM_PARAMS="INSTALLDIRS=vendor" else - PERL_MM_PARAMS="INSTALLDIRS=perl PREFIX=`perl -e 'use Config; print $Config{prefix}'`" + PERL_MM_PARAMS="INSTALLDIRS=perl PREFIX=`$perlpath -e 'use Config; print $Config{prefix}'`" fi - perl_library_dir="(vendor default - `$perlpath -e 'use Config; print $Config{archlib}'`)" + perl_set_use_lib=no else want_perl=yes perl_prefix_note=no PERL_MM_PARAMS="INSTALLDIRS=perl LIB=$withval" - perl_library_dir="PERL_USE_LIB" perl_set_use_lib=yes fi, want_perl=yes) @@ -371,7 +375,7 @@ if test "$want_perl" != "no"; then dnl * complain about them. Normally there's only few options dnl * that we want to keep: dnl * -Ddefine -Uundef -I/path -fopt -mopt - PERL_CFLAGS=`echo $PERL_CFLAGS | $perlpath -pe 's/^(.* )?-[^DUIfm][^ ]+/\1/g; s/^(.* )?\+[^ ]+/\1/g'` + PERL_CFLAGS=`echo $PERL_CFLAGS | $perlpath -pe 's/^(.* )?-@<:@^DUIfm@:>@@<:@^ @:>@+/\1/g; s/^(.* )?\+@<:@^ @:>@+/\1/g'` PERL_EXTRA_OPTS="CCCDLFLAGS=\"-fPIC\"" AC_SUBST(PERL_EXTRA_OPTS) @@ -455,13 +459,37 @@ if test "$want_perl" != "no"; then PERL_STATIC_LIBS=0 fi + # remove any prefix from PERL_MM_OPT + PERL_MM_OPT=`perl -MText::ParseWords -e 'sub qu{$_=shift;s{^(.*?)=(.*)$}{($a,$b)=($1,$2);$b=~s/"/\\\\"/g;qq{$a="$b"}}ge if /@<:@\s"@:>@/;$_} local $,=" "; print map qu($_), grep !/^(INSTALL_BASE|PREFIX)=/, shellwords(@ARGV)' "$PERL_MM_OPT"` # figure out the correct @INC path - we'll need to do this # through MakeMaker since it's difficult to get it right # otherwise. + $perlpath -MExtUtils::MakeMaker -e 'WriteMakefile(NAME => "test", MAKEFILE => "Makefile.test", FIRST_MAKEFILE => "/dev/null", NO_META => 1, NO_MYMETA => 1);' $PERL_MM_PARAMS >/dev/null + echo 'show-INSTALLDIRS:' >> Makefile.test + echo ' @echo $(INSTALLDIRS)' >> Makefile.test + perl_INSTALLDIRS=`$am_make -f Makefile.test show-INSTALLDIRS` + if test "x$perl_INSTALLDIRS" = "xsite"; then + perl_library_dir="site default" + perl_INSTALL_VAR=INSTALLSITEARCH + elif test "x$perl_INSTALLDIRS" = "xvendor"; then + perl_library_dir="vendor default" + perl_INSTALL_VAR=INSTALLVENDORARCH + else + perl_library_dir="module default" + perl_INSTALL_VAR=INSTALLARCHLIB + fi + echo 'show-ARCHLIB:' >> Makefile.test + echo ' @echo $('"$perl_INSTALL_VAR"')' >> Makefile.test + perl_use_lib=`$am_make -f Makefile.test show-ARCHLIB` + rm -f Makefile.test if test "x$perl_set_use_lib" = "xyes"; then - perl -e 'use ExtUtils::MakeMaker; WriteMakefile("NAME" => "test", "MAKEFILE" => "Makefile.test");' $PERL_MM_PARAMS >/dev/null - PERL_USE_LIB=`perl -e 'open(F, "Makefile.test"); while () { chomp; if (/^(\w+) = (.*$)/) { $keys{$1} = $2; } }; $key = $keys{INSTALLARCHLIB}; while ($key =~ /\\$\((\w+)\)/) { $value = $keys{$1}; $key =~ s/\\$\($1\)/$value/; }; print $key;'` - rm -f Makefile.test + if $perlpath -e 'exit ! grep $_ eq $ARGV@<:@0@:>@, grep /^\//, @INC' "$perl_use_lib"; then + perl_library_dir="other path in @INC" + perl_set_use_lib=no + else + perl_library_dir="prepends to @INC with /set perl_use_lib" + PERL_USE_LIB="$perl_use_lib" + fi fi AC_SUBST(perl_module_lib) @@ -477,6 +505,7 @@ if test "$want_perl" != "no"; then AC_SUBST(PERL_CFLAGS) AC_SUBST(PERL_USE_LIB) + AC_SUBST(PERL_MM_OPT) AC_SUBST(PERL_MM_PARAMS) AC_SUBST(PERL_STATIC_LIBS) fi @@ -591,6 +620,25 @@ else want_truecolor=no fi +AH_TEMPLATE(HAS_CURSES, [macros/curses checks]) +AH_TEMPLATE(HAVE_CURSES_IDCOK) +AH_TEMPLATE(HAVE_CURSES_RESIZETERM) +AH_TEMPLATE(HAVE_CURSES_WRESIZE) +AH_TEMPLATE(HAVE_GMODULE) +AH_TEMPLATE(HAVE_NCURSES_USE_DEFAULT_COLORS, [our own curses checks]) +AH_TEMPLATE(HAVE_SOCKS_H, [misc..]) +AH_TEMPLATE(HAVE_STATIC_PERL) +AH_TEMPLATE(HAVE_TERMINFO, [terminfo/termcap]) +AH_TEMPLATE(NO_COLOR_CURSES) +AH_TEMPLATE(PRIuUOFF_T, [printf()-format for uoff_t, eg. "u" or "lu" or "llu"]) +AH_TEMPLATE(SCO_FLAVOR) +AH_TEMPLATE(UOFF_T_INT, [What type should be used for uoff_t]) +AH_TEMPLATE(UOFF_T_LONG) +AH_TEMPLATE(UOFF_T_LONG_LONG) +AH_TEMPLATE(USE_NCURSES) +AH_TEMPLATE(USE_SUNOS_CURSES) +AH_TEMPLATE(USE_SYSV_CURSES) + AC_CONFIG_FILES([ Makefile src/Makefile @@ -692,13 +740,7 @@ if test "x$want_perl" != "xno" -a "x$perl_mod_error" != "x"; then fi if test "x$want_perl" != "xno"; then - if test "$perl_library_dir" = "PERL_USE_LIB"; then - perl_library_dir=$PERL_USE_LIB - fi - if test -z "$perl_library_dir"; then - perl_library_dir="(site default - `$perlpath -e 'use Config; print $Config{sitearch}'`)" - fi - echo "Perl library directory ........... : $perl_library_dir" + echo "Perl library directory ........... : ($perl_library_dir - $perl_use_lib)" if test "x$perl_prefix_note" = "xyes"; then echo " - NOTE: This was automatically set to the same directory you gave with" echo " --prefix. If you want the perl libraries to install to their 'correct'" From affbf71f102cc740aeda180fd3297c1cc6c8f7de Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 11 May 2016 11:43:08 +0200 Subject: [PATCH 066/140] add silent flag to make, should stop GNU make from turning on -w --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 0e5f2f0d..04e2b0b3 100644 --- a/configure.ac +++ b/configure.ac @@ -467,7 +467,7 @@ if test "$want_perl" != "no"; then $perlpath -MExtUtils::MakeMaker -e 'WriteMakefile(NAME => "test", MAKEFILE => "Makefile.test", FIRST_MAKEFILE => "/dev/null", NO_META => 1, NO_MYMETA => 1);' $PERL_MM_PARAMS >/dev/null echo 'show-INSTALLDIRS:' >> Makefile.test echo ' @echo $(INSTALLDIRS)' >> Makefile.test - perl_INSTALLDIRS=`$am_make -f Makefile.test show-INSTALLDIRS` + perl_INSTALLDIRS=`$am_make -s -f Makefile.test show-INSTALLDIRS` if test "x$perl_INSTALLDIRS" = "xsite"; then perl_library_dir="site default" perl_INSTALL_VAR=INSTALLSITEARCH @@ -480,7 +480,7 @@ if test "$want_perl" != "no"; then fi echo 'show-ARCHLIB:' >> Makefile.test echo ' @echo $('"$perl_INSTALL_VAR"')' >> Makefile.test - perl_use_lib=`$am_make -f Makefile.test show-ARCHLIB` + perl_use_lib=`$am_make -s -f Makefile.test show-ARCHLIB` rm -f Makefile.test if test "x$perl_set_use_lib" = "xyes"; then if $perlpath -e 'exit ! grep $_ eq $ARGV@<:@0@:>@, grep /^\//, @INC' "$perl_use_lib"; then From 5538578820550c1a62dc4d0e6451332229eeee75 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 01:26:33 +0200 Subject: [PATCH 067/140] Move utf8.{h,c} from fe-common/core to core. --- src/core/Makefile.am | 1 + src/{fe-common => }/core/utf8.c | 2 ++ src/{fe-common => }/core/utf8.h | 3 +++ src/{fe-common => }/core/wcwidth.c | 0 src/fe-common/core/Makefile.am | 5 ----- src/fe-common/core/module.h | 2 +- src/fe-text/term.h | 2 +- 7 files changed, 8 insertions(+), 7 deletions(-) rename src/{fe-common => }/core/utf8.c (96%) rename src/{fe-common => }/core/utf8.h (93%) rename src/{fe-common => }/core/wcwidth.c (100%) diff --git a/src/core/Makefile.am b/src/core/Makefile.am index fc32e17e..cc200034 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -44,6 +44,7 @@ libcore_a_SOURCES = \ settings.c \ signals.c \ special-vars.c \ + utf8.c \ write-buffer.c structure_headers = \ diff --git a/src/fe-common/core/utf8.c b/src/core/utf8.c similarity index 96% rename from src/fe-common/core/utf8.c rename to src/core/utf8.c index 2d07ea8e..1ab6def9 100644 --- a/src/fe-common/core/utf8.c +++ b/src/core/utf8.c @@ -22,5 +22,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "utf8.h" #include "module.h" +#include "wcwidth.c" diff --git a/src/fe-common/core/utf8.h b/src/core/utf8.h similarity index 93% rename from src/fe-common/core/utf8.h rename to src/core/utf8.h index 3c15dc7d..63261a24 100644 --- a/src/fe-common/core/utf8.h +++ b/src/core/utf8.h @@ -8,6 +8,9 @@ #define is_big5_hi(hi) (0x81 <= (hi) && (hi) <= 0xFE) #define is_big5(hi,lo) (is_big5_hi(hi) && is_big5_lo(lo)) +#include +typedef guint32 unichar; + /* Returns width for character (0-2). */ int mk_wcwidth(unichar c); diff --git a/src/fe-common/core/wcwidth.c b/src/core/wcwidth.c similarity index 100% rename from src/fe-common/core/wcwidth.c rename to src/core/wcwidth.c diff --git a/src/fe-common/core/Makefile.am b/src/fe-common/core/Makefile.am index e755b510..63f91fa6 100644 --- a/src/fe-common/core/Makefile.am +++ b/src/fe-common/core/Makefile.am @@ -24,8 +24,6 @@ libfe_common_core_a_SOURCES = \ fe-queries.c \ fe-server.c \ fe-settings.c \ - utf8.c \ - wcwidth.c \ formats.c \ hilight-text.c \ keyboard.c \ @@ -62,6 +60,3 @@ pkginc_fe_common_core_HEADERS = \ window-items.h \ windows-layout.h \ fe-windows.h - -noinst_HEADERS = \ - utf8.h diff --git a/src/fe-common/core/module.h b/src/fe-common/core/module.h index 51b61b3e..db712ec7 100644 --- a/src/fe-common/core/module.h +++ b/src/fe-common/core/module.h @@ -2,7 +2,7 @@ #define MODULE_NAME "fe-common/core" -typedef guint32 unichar; +#include "utf8.h" typedef struct { time_t time; char *nick; diff --git a/src/fe-text/term.h b/src/fe-text/term.h index 9b726d82..0c7847f6 100644 --- a/src/fe-text/term.h +++ b/src/fe-text/term.h @@ -27,7 +27,7 @@ typedef struct _TERM_WINDOW TERM_WINDOW; #define TERM_TYPE_UTF8 1 #define TERM_TYPE_BIG5 2 -typedef guint32 unichar; +#include "utf8.h" extern TERM_WINDOW *root_window; extern int term_width, term_height; From 5c74a3bb88db0fa32c459f8494e9f5a62a821baa Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 01:39:14 +0200 Subject: [PATCH 068/140] Move advance() from fe-common/core to core. --- src/core/utf8.c | 15 +++++++++++++++ src/core/utf8.h | 5 +++++ src/fe-common/core/formats.c | 16 ---------------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/core/utf8.c b/src/core/utf8.c index 1ab6def9..6daa878a 100644 --- a/src/core/utf8.c +++ b/src/core/utf8.c @@ -26,3 +26,18 @@ #include "module.h" #include "wcwidth.c" +int advance(char const **str, gboolean utf8) +{ + if (utf8) { + gunichar c; + + c = g_utf8_get_char(*str); + *str = g_utf8_next_char(*str); + + return unichar_isprint(c) ? mk_wcwidth(c) : 1; + } else { + *str += 1; + + return 1; + } +} diff --git a/src/core/utf8.h b/src/core/utf8.h index 63261a24..09397f69 100644 --- a/src/core/utf8.h +++ b/src/core/utf8.h @@ -14,6 +14,11 @@ typedef guint32 unichar; /* Returns width for character (0-2). */ int mk_wcwidth(unichar c); +/* Advance the str pointer one character further; return the number of columns + * occupied by the skipped character. + */ +int advance(char const **str, gboolean utf8); + #define unichar_isprint(c) (((c) & ~0x80) >= 32) #define is_utf8_leading(c) (((c) & 0xc0) != 0x80) diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index ccf48394..7daecfcf 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -420,22 +420,6 @@ void format_create_dest_tag(TEXT_DEST_REC *dest, void *server, window_find_closest(server, target, level); } -static int advance (char const **str, gboolean utf8) -{ - if (utf8) { - gunichar c; - - c = g_utf8_get_char(*str); - *str = g_utf8_next_char(*str); - - return unichar_isprint(c) ? mk_wcwidth(c) : 1; - } else { - *str += 1; - - return 1; - } -} - /* Return length of text part in string (ie. without % codes) */ int format_get_length(const char *str) { From b0afcc96dbc13cf3a5ed94686bb227ab0d86ceaa Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 01:52:37 +0200 Subject: [PATCH 069/140] Rename advance() into string_advance(). --- src/core/utf8.c | 2 +- src/core/utf8.h | 2 +- src/fe-common/core/formats.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/utf8.c b/src/core/utf8.c index 6daa878a..1daaf03f 100644 --- a/src/core/utf8.c +++ b/src/core/utf8.c @@ -26,7 +26,7 @@ #include "module.h" #include "wcwidth.c" -int advance(char const **str, gboolean utf8) +int string_advance(char const **str, gboolean utf8) { if (utf8) { gunichar c; diff --git a/src/core/utf8.h b/src/core/utf8.h index 09397f69..50ee0886 100644 --- a/src/core/utf8.h +++ b/src/core/utf8.h @@ -17,7 +17,7 @@ int mk_wcwidth(unichar c); /* Advance the str pointer one character further; return the number of columns * occupied by the skipped character. */ -int advance(char const **str, gboolean utf8); +int string_advance(char const **str, gboolean utf8); #define unichar_isprint(c) (((c) & ~0x80) >= 32) #define is_utf8_leading(c) (((c) & 0xc0) != 0x80) diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index 7daecfcf..def03e10 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -449,7 +449,7 @@ int format_get_length(const char *str) len++; } - len += advance(&str, utf8); + len += string_advance(&str, utf8); } g_string_free(tmp, TRUE); @@ -491,7 +491,7 @@ int format_real_length(const char *str, int len) } oldstr = str; - len -= advance(&str, utf8); + len -= string_advance(&str, utf8); if (len < 0) str = oldstr; } From 2c8648a9c889fc0a7c4b24367a3f81f08dedccb2 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 02:10:02 +0200 Subject: [PATCH 070/140] Introduce string_policy(). --- src/core/utf8.c | 13 +++++++++++++ src/core/utf8.h | 14 ++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/core/utf8.c b/src/core/utf8.c index 1daaf03f..d931ba19 100644 --- a/src/core/utf8.c +++ b/src/core/utf8.c @@ -25,6 +25,8 @@ #include "utf8.h" #include "module.h" #include "wcwidth.c" +/* Provide is_utf8(): */ +#include "recode.h" int string_advance(char const **str, gboolean utf8) { @@ -41,3 +43,14 @@ int string_advance(char const **str, gboolean utf8) return 1; } } + +int string_policy(const char *str) +{ + if (is_utf8()) { + if (!str || g_utf8_validate(str, -1, NULL)) { + /* No string provided or valid UTF-8 string: treat as UTF-8: */ + return TREAT_STRING_AS_UTF8; + } + } + return TREAT_STRING_AS_BYTES; +} diff --git a/src/core/utf8.h b/src/core/utf8.h index 50ee0886..fa11b737 100644 --- a/src/core/utf8.h +++ b/src/core/utf8.h @@ -19,6 +19,20 @@ int mk_wcwidth(unichar c); */ int string_advance(char const **str, gboolean utf8); +/* TREAT_STRING_AS_BYTES means strings are to be treated using strncpy, + * strnlen, etc. + * TREAT_STRING_AS_UTF8 means strings are to be treated using g_utf8_* + * functions. + */ +#define TREAT_STRING_AS_BYTES 0 +#define TREAT_STRING_AS_UTF8 1 + +/* Return how the str string ought to be treated: TREAT_STRING_AS_UTF8 if the + * terminal handles UTF-8 and if the string appears to be a valid UTF-8 string; + * TREAT_STRING_AS_BYTES otherwise. + */ +int string_policy(const char *str); + #define unichar_isprint(c) (((c) & ~0x80) >= 32) #define is_utf8_leading(c) (((c) & 0xc0) != 0x80) From 21c07c006066115af4604e26cd89cf60f94a7d53 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 02:27:19 +0200 Subject: [PATCH 071/140] Leverage string_policy(). --- src/core/utf8.c | 5 +++-- src/core/utf8.h | 2 +- src/fe-common/core/formats.c | 8 ++++---- src/fe-text/gui-entry.c | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/core/utf8.c b/src/core/utf8.c index d931ba19..c9303d19 100644 --- a/src/core/utf8.c +++ b/src/core/utf8.c @@ -28,9 +28,9 @@ /* Provide is_utf8(): */ #include "recode.h" -int string_advance(char const **str, gboolean utf8) +int string_advance(char const **str, int policy) { - if (utf8) { + if (policy == TREAT_STRING_AS_UTF8) { gunichar c; c = g_utf8_get_char(*str); @@ -38,6 +38,7 @@ int string_advance(char const **str, gboolean utf8) return unichar_isprint(c) ? mk_wcwidth(c) : 1; } else { + /* Assume TREAT_STRING_AS_BYTES: */ *str += 1; return 1; diff --git a/src/core/utf8.h b/src/core/utf8.h index fa11b737..f1a8f0e1 100644 --- a/src/core/utf8.h +++ b/src/core/utf8.h @@ -17,7 +17,7 @@ int mk_wcwidth(unichar c); /* Advance the str pointer one character further; return the number of columns * occupied by the skipped character. */ -int string_advance(char const **str, gboolean utf8); +int string_advance(char const **str, int policy); /* TREAT_STRING_AS_BYTES means strings are to be treated using strncpy, * strnlen, etc. diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index def03e10..3e88426f 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -425,12 +425,12 @@ int format_get_length(const char *str) { GString *tmp; int len; - gboolean utf8; + int utf8; int adv = 0; g_return_val_if_fail(str != NULL, 0); - utf8 = is_utf8() && g_utf8_validate(str, -1, NULL); + utf8 = string_policy(str); tmp = g_string_new(NULL); len = 0; @@ -464,12 +464,12 @@ int format_real_length(const char *str, int len) GString *tmp; const char *start; const char *oldstr; - gboolean utf8; + int utf8; int adv = 0; g_return_val_if_fail(str != NULL, 0); g_return_val_if_fail(len >= 0, 0); - utf8 = is_utf8() && g_utf8_validate(str, -1, NULL); + utf8 = string_policy(str); start = str; tmp = g_string_new(NULL); diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 63dda34e..beea2273 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -367,7 +367,7 @@ static int scrlen_str(const char *str) g_return_val_if_fail(str != NULL, 0); str = stripped = strip_codes(str); - if (is_utf8() && g_utf8_validate(str, -1, NULL)) { + if (string_policy(str) == TREAT_STRING_AS_UTF8) { while (*str != '\0') { gunichar c; From 35b3ccc6a407f83eba4f0c3787cc5c174bd3385c Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 02:47:26 +0200 Subject: [PATCH 072/140] Introduce string_length() and string_width(). --- src/core/utf8.c | 34 ++++++++++++++++++++++++++++++++++ src/core/utf8.h | 9 +++++++++ 2 files changed, 43 insertions(+) diff --git a/src/core/utf8.c b/src/core/utf8.c index c9303d19..7c75c374 100644 --- a/src/core/utf8.c +++ b/src/core/utf8.c @@ -55,3 +55,37 @@ int string_policy(const char *str) } return TREAT_STRING_AS_BYTES; } + +int string_length(const char *str, int policy) +{ + g_return_val_if_fail(str != NULL, 0); + + if (policy == -1) { + policy = string_policy(str); + } + + if (policy == TREAT_STRING_AS_UTF8) { + return g_utf8_strlen(str, -1); + } + else { + /* Assume TREAT_STRING_AS_BYTES: */ + return strlen(str); + } +} + +int string_width(const char *str, int policy) +{ + int len; + + g_return_val_if_fail(str != NULL, 0); + + if (policy == -1) { + policy = string_policy(str); + } + + len = 0; + while (*str != '\0') { + len += string_advance(&str, policy); + } + return len; +} diff --git a/src/core/utf8.h b/src/core/utf8.h index f1a8f0e1..6f02c5a0 100644 --- a/src/core/utf8.h +++ b/src/core/utf8.h @@ -33,6 +33,15 @@ int string_advance(char const **str, int policy); */ int string_policy(const char *str); +/* Return the length of the str string according to the given policy; if policy + * is -1, this function will call string_policy(). + */ +int string_length(const char *str, int policy); +/* Return the screen width of the str string according to the given policy; if + * policy is -1, this function will call string_policy(). + */ +int string_width(const char *str, int policy); + #define unichar_isprint(c) (((c) & ~0x80) >= 32) #define is_utf8_leading(c) (((c) & 0xc0) != 0x80) From 719efc44a3c3c3db8f12b6ff40d2021837d9a902 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 03:04:08 +0200 Subject: [PATCH 073/140] Introduce string_chars_for_width(). --- src/core/utf8.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/core/utf8.h | 6 ++++++ 2 files changed, 50 insertions(+) diff --git a/src/core/utf8.c b/src/core/utf8.c index 7c75c374..d1f58599 100644 --- a/src/core/utf8.c +++ b/src/core/utf8.c @@ -89,3 +89,47 @@ int string_width(const char *str, int policy) } return len; } + +int string_chars_for_width(const char *str, int policy, unsigned int n, unsigned int *bytes) +{ + const char *c, *previous_c; + int str_width, char_width, char_count; + + g_return_val_if_fail(str != NULL, -1); + + /* Handle the dummy case where n is 0: */ + if (!n) { + if (bytes) { + *bytes = 0; + } + return 0; + } + + if (policy == -1) { + policy = string_policy(str); + } + + /* Iterate over characters until we reach n: */ + char_count = 0; + str_width = 0; + c = str; + while (*c != '\0') { + previous_c = c; + char_width = string_advance(&c, policy); + if (str_width + char_width > n) { + /* We stepped beyond n, get one step back and stop there: */ + c = previous_c; + break; + } + ++ char_count; + str_width += char_width; + } + /* At this point, we know that char_count characters reach str_width + * columns, which is less than or equal to n. */ + + /* Optionally provide the equivalent amount of bytes: */ + if (bytes) { + *bytes = c - str; + } + return char_count; +} diff --git a/src/core/utf8.h b/src/core/utf8.h index 6f02c5a0..411b2048 100644 --- a/src/core/utf8.h +++ b/src/core/utf8.h @@ -42,6 +42,12 @@ int string_length(const char *str, int policy); */ int string_width(const char *str, int policy); +/* Return the amount of characters from str it takes to reach n columns, or -1 if + * str is NULL. Optionally return the equivalent amount of bytes. + * If policy is -1, this function will call string_policy(). + */ +int string_chars_for_width(const char *str, int policy, unsigned int n, unsigned int *bytes); + #define unichar_isprint(c) (((c) & ~0x80) >= 32) #define is_utf8_leading(c) (((c) & 0xc0) != 0x80) From 09ca3ad48f57b7febd6ad353fb38dbe9234e7e70 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 03:31:23 +0200 Subject: [PATCH 074/140] Fix indentation of display_sorted_nicks(). This was done assuming an "indent with tab, align with spaces" approach. get_alignment also benefited from a minor indentation fix. --- src/core/special-vars.c | 2 +- src/fe-common/core/fe-channels.c | 64 ++++++++++++++++---------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/core/special-vars.c b/src/core/special-vars.c index 4dcc3d2f..d6794d96 100644 --- a/src/core/special-vars.c +++ b/src/core/special-vars.c @@ -340,7 +340,7 @@ static char *get_alignment(const char *text, int align, int flags, char pad) } ret = str->str; - g_string_free(str, FALSE); + g_string_free(str, FALSE); return ret; } diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index 046d641a..fd44be11 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -328,35 +328,35 @@ static int get_nick_length(void *data) static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) { - WINDOW_REC *window; + WINDOW_REC *window; TEXT_DEST_REC dest; GString *str; GSList *tmp; - char *format, *stripped, *prefix_format; + char *format, *stripped, *prefix_format; char *linebuf, nickmode[2] = { 0, 0 }; int *columns, cols, rows, last_col_rows, col, row, max_width; - int item_extra, linebuf_size, formatnum; + int item_extra, linebuf_size, formatnum; window = window_find_closest(channel->server, channel->visible_name, - MSGLEVEL_CLIENTCRAP); - max_width = window->width; + MSGLEVEL_CLIENTCRAP); + max_width = window->width; - /* get the length of item extra stuff ("[ ] ") */ + /* get the length of item extra stuff ("[ ] ") */ format = format_get_text(MODULE_NAME, NULL, - channel->server, channel->visible_name, - TXT_NAMES_NICK, " ", ""); + channel->server, channel->visible_name, + TXT_NAMES_NICK, " ", ""); stripped = strip_codes(format); item_extra = strlen(stripped); - g_free(stripped); + g_free(stripped); g_free(format); if (settings_get_int("names_max_width") > 0 && settings_get_int("names_max_width") < max_width) max_width = settings_get_int("names_max_width"); - /* remove width of the timestamp from max_width */ + /* remove width of the timestamp from max_width */ format_create_dest(&dest, channel->server, channel->visible_name, - MSGLEVEL_CLIENTCRAP, NULL); + MSGLEVEL_CLIENTCRAP, NULL); format = format_get_line_start(current_theme, &dest, time(NULL)); if (format != NULL) { stripped = strip_codes(format); @@ -365,11 +365,11 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) g_free(format); } - /* remove width of the prefix from max_width */ + /* remove width of the prefix from max_width */ prefix_format = format_get_text(MODULE_NAME, NULL, - channel->server, channel->visible_name, - TXT_NAMES_PREFIX, - channel->visible_name); + channel->server, channel->visible_name, + TXT_NAMES_PREFIX, + channel->visible_name); if (prefix_format != NULL) { stripped = strip_codes(prefix_format); max_width -= strlen(stripped); @@ -384,19 +384,19 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) /* calculate columns */ cols = get_max_column_count(nicklist, get_nick_length, max_width, - settings_get_int("names_max_columns"), - item_extra, 3, &columns, &rows); + settings_get_int("names_max_columns"), + item_extra, 3, &columns, &rows); nicklist = columns_sort_list(nicklist, rows); - /* rows in last column */ + /* rows in last column */ last_col_rows = rows-(cols*rows-g_slist_length(nicklist)); if (last_col_rows == 0) - last_col_rows = rows; + last_col_rows = rows; str = g_string_new(prefix_format); linebuf_size = max_width+1; linebuf = g_malloc(linebuf_size); - col = 0; row = 0; + col = 0; row = 0; for (tmp = nicklist; tmp != NULL; tmp = tmp->next) { NICK_REC *rec = tmp->data; @@ -407,39 +407,39 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) if (linebuf_size < columns[col]-item_extra+1) { linebuf_size = (columns[col]-item_extra+1)*2; - linebuf = g_realloc(linebuf, linebuf_size); + linebuf = g_realloc(linebuf, linebuf_size); } memset(linebuf, ' ', columns[col]-item_extra); linebuf[columns[col]-item_extra] = '\0'; memcpy(linebuf, rec->nick, strlen(rec->nick)); - formatnum = rec->op ? TXT_NAMES_NICK_OP : - rec->halfop ? TXT_NAMES_NICK_HALFOP : - rec->voice ? TXT_NAMES_NICK_VOICE : - TXT_NAMES_NICK; + formatnum = rec->op ? TXT_NAMES_NICK_OP : + rec->halfop ? TXT_NAMES_NICK_HALFOP : + rec->voice ? TXT_NAMES_NICK_VOICE : + TXT_NAMES_NICK; format = format_get_text(MODULE_NAME, NULL, - channel->server, - channel->visible_name, - formatnum, nickmode, linebuf); + channel->server, + channel->visible_name, + formatnum, nickmode, linebuf); g_string_append(str, format); g_free(format); if (++col == cols) { printtext(channel->server, channel->visible_name, - MSGLEVEL_CLIENTCRAP, "%s", str->str); + MSGLEVEL_CLIENTCRAP, "%s", str->str); g_string_truncate(str, 0); if (prefix_format != NULL) - g_string_assign(str, prefix_format); + g_string_assign(str, prefix_format); col = 0; row++; if (row == last_col_rows) - cols--; + cols--; } } if (str->len > strlen(prefix_format)) { printtext(channel->server, channel->visible_name, - MSGLEVEL_CLIENTCRAP, "%s", str->str); + MSGLEVEL_CLIENTCRAP, "%s", str->str); } g_slist_free(nicklist); From 97a4ee78fd08e58fce62c6c0b22de94b625c90f6 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 03:42:56 +0200 Subject: [PATCH 075/140] get_alignment: handle UTF-8 strings. get_alignment now works with columns (width), not bytes, although it is liable to work with bytes if the given text is not a valid UTF-8 string. --- src/core/special-vars.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/core/special-vars.c b/src/core/special-vars.c index d6794d96..64011b8e 100644 --- a/src/core/special-vars.c +++ b/src/core/special-vars.c @@ -25,6 +25,7 @@ #include "settings.h" #include "servers.h" #include "misc.h" +#include "utf8.h" #define ALIGN_RIGHT 0x01 #define ALIGN_CUT 0x02 @@ -320,18 +321,24 @@ static char *get_alignment(const char *text, int align, int flags, char pad) { GString *str; char *ret; + int policy; + unsigned int cut_bytes; g_return_val_if_fail(text != NULL, NULL); + policy = string_policy(text); + str = g_string_new(text); /* cut */ - if ((flags & ALIGN_CUT) && align > 0 && str->len > align) - g_string_truncate(str, align); + if ((flags & ALIGN_CUT) && align > 0 && string_width(text, policy) > align) { + string_chars_for_width(text, policy, align, &cut_bytes); + g_string_truncate(str, cut_bytes); + } /* add pad characters */ if (flags & ALIGN_PAD) { - while (str->len < align) { + while (string_width(str->str, policy) < align) { if (flags & ALIGN_RIGHT) g_string_prepend_c(str, pad); else From f1b5b515b9f91866d241ba6dbf5e1db6827ff61a Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 03:51:48 +0200 Subject: [PATCH 076/140] Make get_alignment() available outside special-vars.c --- src/core/special-vars.c | 6 +----- src/core/special-vars.h | 7 +++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/special-vars.c b/src/core/special-vars.c index 64011b8e..fe6bbed2 100644 --- a/src/core/special-vars.c +++ b/src/core/special-vars.c @@ -27,10 +27,6 @@ #include "misc.h" #include "utf8.h" -#define ALIGN_RIGHT 0x01 -#define ALIGN_CUT 0x02 -#define ALIGN_PAD 0x04 - #define isvarchar(c) \ (i_isalnum(c) || (c) == '_') @@ -317,7 +313,7 @@ static int get_alignment_args(char **data, int *align, int *flags, char *pad) } /* return the aligned text */ -static char *get_alignment(const char *text, int align, int flags, char pad) +char *get_alignment(const char *text, int align, int flags, char pad) { GString *str; char *ret; diff --git a/src/core/special-vars.h b/src/core/special-vars.h index 11262dad..300dae0e 100644 --- a/src/core/special-vars.h +++ b/src/core/special-vars.h @@ -9,9 +9,16 @@ #define PARSE_FLAG_ESCAPE_THEME 0x08 /* if any arguments/variables contain { or } chars, escape them with % */ #define PARSE_FLAG_ONLY_ARGS 0x10 /* expand only arguments ($0 $1 etc.) but no other $variables */ +#define ALIGN_RIGHT 0x01 +#define ALIGN_CUT 0x02 +#define ALIGN_PAD 0x04 + typedef char* (*SPECIAL_HISTORY_FUNC) (const char *text, void *item, int *free_ret); +/* Cut and/or pad text so it takes exactly "align" characters on the screen */ +char *get_alignment(const char *text, int align, int flags, char pad); + /* Parse and expand text after '$' character. return value has to be g_free()'d if `free_ret' is TRUE. */ char *parse_special(char **cmd, SERVER_REC *server, void *item, From 29beafcf6fd50ecb8a9f3b2b642c2d29c022a4e3 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 04:08:15 +0200 Subject: [PATCH 077/140] Improve UTF-8 handling in display_sorted_nicks(). --- src/fe-common/core/fe-channels.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index fd44be11..d87c4ce5 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -26,6 +26,8 @@ #include "levels.h" #include "misc.h" #include "settings.h" +#include "special-vars.h" +#include "utf8.h" #include "chat-protocols.h" #include "chatnets.h" @@ -323,7 +325,7 @@ static void cmd_channel_remove(const char *data) static int get_nick_length(void *data) { - return strlen(((NICK_REC *) data)->nick); + return string_width(((NICK_REC *) data)->nick, -1); } static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) @@ -333,9 +335,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) GString *str; GSList *tmp; char *format, *stripped, *prefix_format; - char *linebuf, nickmode[2] = { 0, 0 }; + char *aligned_nick, nickmode[2] = { 0, 0 }; int *columns, cols, rows, last_col_rows, col, row, max_width; - int item_extra, linebuf_size, formatnum; + int item_extra, formatnum; window = window_find_closest(channel->server, channel->visible_name, MSGLEVEL_CLIENTCRAP); @@ -394,7 +396,6 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) last_col_rows = rows; str = g_string_new(prefix_format); - linebuf_size = max_width+1; linebuf = g_malloc(linebuf_size); col = 0; row = 0; for (tmp = nicklist; tmp != NULL; tmp = tmp->next) { @@ -405,13 +406,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) else nickmode[0] = ' '; - if (linebuf_size < columns[col]-item_extra+1) { - linebuf_size = (columns[col]-item_extra+1)*2; - linebuf = g_realloc(linebuf, linebuf_size); - } - memset(linebuf, ' ', columns[col]-item_extra); - linebuf[columns[col]-item_extra] = '\0'; - memcpy(linebuf, rec->nick, strlen(rec->nick)); + aligned_nick = get_alignment(rec->nick, + columns[col]-item_extra, + ALIGN_PAD, ' '); formatnum = rec->op ? TXT_NAMES_NICK_OP : rec->halfop ? TXT_NAMES_NICK_HALFOP : @@ -420,8 +417,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) format = format_get_text(MODULE_NAME, NULL, channel->server, channel->visible_name, - formatnum, nickmode, linebuf); + formatnum, nickmode, aligned_nick); g_string_append(str, format); + g_free(aligned_nick); g_free(format); if (++col == cols) { @@ -446,7 +444,6 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) g_string_free(str, TRUE); g_free_not_null(columns); g_free_not_null(prefix_format); - g_free(linebuf); } void fe_channels_nicklist(CHANNEL_REC *channel, int flags) From 72064de9fe064a7536b501fc470edf75fc393314 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 04:19:38 +0200 Subject: [PATCH 078/140] Simplify scrlen_str() using string_width(). --- src/fe-text/gui-entry.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index beea2273..949a43d3 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -366,22 +366,8 @@ static int scrlen_str(const char *str) char *stripped; g_return_val_if_fail(str != NULL, 0); - str = stripped = strip_codes(str); - if (string_policy(str) == TREAT_STRING_AS_UTF8) { - - while (*str != '\0') { - gunichar c; - - c = g_utf8_get_char(str); - str = g_utf8_next_char(str); - - len += unichar_isprint(c) ? mk_wcwidth(c) : 1; - } - - } else { - len = strlen(str); - } - + stripped = strip_codes(str); + len = string_width(stripped, -1); g_free(stripped); return len; } From a26a387545ae530cb3222fd4daa5ed088e068de2 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 17:31:11 +0200 Subject: [PATCH 079/140] Adjust some conditions. --- src/core/utf8.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/utf8.c b/src/core/utf8.c index d1f58599..29b277e1 100644 --- a/src/core/utf8.c +++ b/src/core/utf8.c @@ -48,7 +48,7 @@ int string_advance(char const **str, int policy) int string_policy(const char *str) { if (is_utf8()) { - if (!str || g_utf8_validate(str, -1, NULL)) { + if (str == NULL || g_utf8_validate(str, -1, NULL)) { /* No string provided or valid UTF-8 string: treat as UTF-8: */ return TREAT_STRING_AS_UTF8; } @@ -98,8 +98,8 @@ int string_chars_for_width(const char *str, int policy, unsigned int n, unsigned g_return_val_if_fail(str != NULL, -1); /* Handle the dummy case where n is 0: */ - if (!n) { - if (bytes) { + if (n == 0) { + if (bytes != NULL) { *bytes = 0; } return 0; @@ -128,7 +128,7 @@ int string_chars_for_width(const char *str, int policy, unsigned int n, unsigned * columns, which is less than or equal to n. */ /* Optionally provide the equivalent amount of bytes: */ - if (bytes) { + if (bytes != NULL) { *bytes = c - str; } return char_count; From 5d69b4c4a7d334ca29e61969712f5f8eedfa5cd9 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Fri, 13 May 2016 17:35:47 +0200 Subject: [PATCH 080/140] Convert string policies from #define to enum. --- src/core/utf8.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/utf8.h b/src/core/utf8.h index 411b2048..5bb53193 100644 --- a/src/core/utf8.h +++ b/src/core/utf8.h @@ -24,8 +24,10 @@ int string_advance(char const **str, int policy); * TREAT_STRING_AS_UTF8 means strings are to be treated using g_utf8_* * functions. */ -#define TREAT_STRING_AS_BYTES 0 -#define TREAT_STRING_AS_UTF8 1 +enum str_policy { + TREAT_STRING_AS_BYTES, + TREAT_STRING_AS_UTF8 +}; /* Return how the str string ought to be treated: TREAT_STRING_AS_UTF8 if the * terminal handles UTF-8 and if the string appears to be a valid UTF-8 string; From 8b847034efa20f23c96f35522f9f7615a5ab498c Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 11 May 2016 21:51:41 +0200 Subject: [PATCH 081/140] update news and authors --- AUTHORS | 1 + NEWS | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/AUTHORS b/AUTHORS index 7ded5017..cb48e07a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -97,3 +97,4 @@ Other patches (grep for "patch" in ChangeLog) by: Paul Johnson KindOne Fabian Kurz + Todd Pratt diff --git a/NEWS b/NEWS index 0d450b02..00d35f9d 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,27 @@ v0.8.20-head 2016-xx-xx The Irssi team * Removed --disable-ipv6 + * /connect Network now aborts with an error if no servers have been + added to that network. + * /dcc commands now use quotes around spaces consistently. + irssiproxy can now forward all tags through a single port. + + irssiproxy can also listen on unix sockets. + send channel -botcmds immediately when no mask is specified (#175). + + the kill buffer now remembers consecutive kills. + New bindings were added: yank_next_cutbuffer and append_next_kill + + connections will avoid looking up IPv6 addresses if the machine does + not have an IPv6 address assigned (exact behaviour is implementation + defined). + + Fix potential crash if scripts insert undef values into the completion + list. + + Paste warning is now also shown on pasting overlong lines. + + autolog_ignore_targets and activity_hide_targets learn a new syntax + tag/* and * to ignore whole networks or everything. + + /hilight got a -matchcase flag to hilight case sensitively (#421). + - /squery and /servlist commands have been restored. + - Where Irssi would previously only report "System error" on connect, + it will now try harder to retrieve the system error message. + - IP addresses are no longer stored when resolve_reverse_lookup is + used. v0.8.19 2016-03-23 The Irssi team - Fixed regression when joining and parting channels on IRCnet (#435) From 5995c0619dc2bf6d789e5b93abe8a531ceb1f45a Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 18 May 2016 14:39:52 +0200 Subject: [PATCH 082/140] abi increase for #480 --- src/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.h b/src/common.h index 4fd6d331..66892b78 100644 --- a/src/common.h +++ b/src/common.h @@ -6,7 +6,7 @@ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ -#define IRSSI_ABI_VERSION 4 +#define IRSSI_ABI_VERSION 5 #define DEFAULT_SERVER_ADD_PORT 6667 From 8d5edff5151761d5b069badad836cb26724ae1ae Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 18 May 2016 14:43:54 +0200 Subject: [PATCH 083/140] update news and authors --- AUTHORS | 1 + NEWS | 1 + 2 files changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index cb48e07a..eea359cc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -98,3 +98,4 @@ Other patches (grep for "patch" in ChangeLog) by: KindOne Fabian Kurz Todd Pratt + xavierog diff --git a/NEWS b/NEWS index 00d35f9d..5312aef5 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,7 @@ v0.8.20-head 2016-xx-xx The Irssi team it will now try harder to retrieve the system error message. - IP addresses are no longer stored when resolve_reverse_lookup is used. + - /names and $[...] now uses utf8 string operations (#40, #411). v0.8.19 2016-03-23 The Irssi team - Fixed regression when joining and parting channels on IRCnet (#435) From 36beddc64f881c2c9618b449ed5c590d41872455 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 18 May 2016 15:32:35 +0200 Subject: [PATCH 084/140] test make dist in travis --- .travis.yml | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 46f58766..804dc58c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,11 +16,31 @@ addons: before_install: - perl -V + - ./autogen.sh --with-proxy --with-bot --with-perl=module + - make dist + - cd .. + - tar xaf */irssi-*.tar.* + - cd irssi-* -install: true - -script: - - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build - - cat config.log +install: + - ./configure --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build - make CFLAGS="-Wall -Werror" - make install + +before_script: + - cd + - mkdir irssi-test + - echo echo automated irssi launch test > irssi-test/startup; + echo ^set settings_autosave off >> irssi-test/startup; + echo ^set -clear log_close_string >> irssi-test/startup; + echo ^set -clear log_day_changed >> irssi-test/startup; + echo ^set -clear log_open_string >> irssi-test/startup; + echo ^set log_timestamp '* ' >> irssi-test/startup; + echo ^window log on >> irssi-test/startup + - echo load perl >> irssi-test/startup + - echo load proxy >> irssi-test/startup + - echo ^quit >> irssi-test/startup + - irssi-build/bin/irssi --home irssi-test + - cat irc.log.* + +script: true From 02221eae373c5db93d1c715d836d79c724d361c7 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 18 May 2016 15:42:09 +0200 Subject: [PATCH 085/140] fix dist compilation failure remove illegal wcwidth.c include and compile wcwidth.c correct #include in wcwidth.c fallout from #480 --- src/core/Makefile.am | 2 ++ src/core/utf8.c | 2 +- src/core/wcwidth.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/Makefile.am b/src/core/Makefile.am index cc200034..af323234 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -45,6 +45,7 @@ libcore_a_SOURCES = \ signals.c \ special-vars.c \ utf8.c \ + wcwidth.c \ write-buffer.c structure_headers = \ @@ -94,6 +95,7 @@ pkginc_core_HEADERS = \ settings.h \ signals.h \ special-vars.h \ + utf8.h \ window-item-def.h \ write-buffer.h \ $(structure_headers) diff --git a/src/core/utf8.c b/src/core/utf8.c index 29b277e1..c53d8816 100644 --- a/src/core/utf8.c +++ b/src/core/utf8.c @@ -24,7 +24,7 @@ #include "utf8.h" #include "module.h" -#include "wcwidth.c" + /* Provide is_utf8(): */ #include "recode.h" diff --git a/src/core/wcwidth.c b/src/core/wcwidth.c index 80d20fa1..711c4646 100644 --- a/src/core/wcwidth.c +++ b/src/core/wcwidth.c @@ -59,7 +59,7 @@ * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c */ -#include "module.h" +#include "utf8.h" struct interval { int first; From f1d0c8ff99c4a0627d96c6ae0db39d917689fb07 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 1 Jun 2016 22:29:13 +0200 Subject: [PATCH 086/140] Correct the name of the emitted signal. There's a typo in 'sasl_fail', the signal that's emitted should be 'server sasl failure' and not 'server sasl fail'. --- src/irc/core/sasl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index b74b6a8c..f080ae59 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -71,7 +71,7 @@ static void sasl_fail(IRC_SERVER_REC *server, const char *data, const char *from params = event_get_params(data, 2, NULL, &error); - signal_emit("server sasl fail", 2, server, error); + signal_emit("server sasl failure", 2, server, error); /* Terminate the negotiation */ cap_finish_negotiation(server); From 03aec7d3b369231b52960db7238f30cc46dd8e01 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Thu, 10 Dec 2015 14:07:07 +0100 Subject: [PATCH 087/140] silent make perl --- src/perl/Makefile.am | 14 ++++++- src/perl/Makefile_silent.pm | 76 ++++++++++++++++++++++++++++++++++ src/perl/common/Makefile.PL.in | 2 +- src/perl/irc/Makefile.PL.in | 2 +- src/perl/textui/Makefile.PL.in | 2 +- src/perl/ui/Makefile.PL.in | 2 +- 6 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 src/perl/Makefile_silent.pm diff --git a/src/perl/Makefile.am b/src/perl/Makefile.am index a09c49a5..b17fd664 100644 --- a/src/perl/Makefile.am +++ b/src/perl/Makefile.am @@ -117,16 +117,26 @@ textui_sources = \ EXTRA_DIST = \ get-signals.pl \ irssi-core.pl \ + Makefile_silent.pm \ $(common_sources) \ $(irc_sources) \ $(ui_sources) \ $(textui_sources) +am_v_pl__show_gen = $(am__v_pl__show_gen_$(V)) +am_v_pl__hide_gen = $(am__v_pl__hide_gen_$(V)) +am__v_pl__show_gen_ = $(am__v_pl__show_gen_$(AM_DEFAULT_VERBOSITY)) +am__v_pl__hide_gen_ = $(am__v_pl__hide_gen_$(AM_DEFAULT_VERBOSITY)) +am__v_pl__show_gen_0 = echo " GEN " $$dir ; +am__v_pl__hide_gen_0 = > /dev/null +am__v_pl__show_gen_1 = +am__v_pl__hide_gen_1 = + all-local: - for dir in $(perl_dirs); do \ + $(AM_V_GEN)for dir in $(perl_dirs); do \ cd $$dir && \ if [ ! -f Makefile ]; then \ - $(perlpath) Makefile.PL $(PERL_MM_PARAMS); \ + $(am_v_pl__show_gen)$(perlpath) Makefile.PL $(PERL_MM_PARAMS) $(am_v_pl__hide_gen); \ fi && \ ($(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" $(PERL_EXTRA_OPTS) || \ $(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \ diff --git a/src/perl/Makefile_silent.pm b/src/perl/Makefile_silent.pm new file mode 100644 index 00000000..e6036c98 --- /dev/null +++ b/src/perl/Makefile_silent.pm @@ -0,0 +1,76 @@ +push @ExtUtils::MakeMaker::Overridable, qw(pm_to_blib); +my $verb = $AM_DEFAULT_VERBOSITY; +package MY { + sub _center { + my $z = shift; + length $z == 2 ? " $z " : length $z == 4 ? " $z " : " $z " + } + sub _silent_cmd { + my $z = shift; + $z =~ s{\t(?:- ?)?\K(?=\$\((?|(CC)CMD|(XS)UBPPRUN|(LD|MV|CHMOD)|(RM)_R?F|(CP)_NONEMPTY|FULL_(AR)\)))}{\$(PL_AM_V_$1)}g; + $z + } + sub c_o { _silent_cmd(shift->SUPER::c_o(@_)) } + sub xs_c { _silent_cmd(shift->SUPER::xs_c(@_)) } + sub xs_o { _silent_cmd(shift->SUPER::xs_o(@_)) } + sub dynamic_lib { _silent_cmd(shift->SUPER::dynamic_lib(@_)) } + sub static_lib { _silent_cmd(shift->SUPER::static_lib(@_)) } + sub dynamic_bs { + my $ret = shift->SUPER::dynamic_bs(@_); + $ret =~ s{Running Mkbootstrap for}{\$(PL_AM_V_BS_Text)}g; + _silent_cmd($ret) + } + sub pm_to_blib { + my $ret = shift->SUPER::pm_to_blib(@_); + $ret =~ s{^(\t(?:- ?)?)(?:\$\(NOECHO\) ?)?(.*-e ['"]pm_to_blib(.*\\\n)*.*)$}{$1\$(PL_AM_V_BLIB)$2\$(PL_AM_V_BLIB_Hide)}mg; + $ret + } + sub post_constants { + my $ret = shift->SUPER::post_constants(@_); + my @terse = qw(cc xs ld chmod cp ar blib); + my @silent = qw(mv rm); + my @special = qw(BLIB_Hide); + + #default verbosity from command line parameter + $ret .= " +AM_DEFAULT_VERBOSITY = @{[$verb ? 1 : 0]} +"; + #default options forward + $ret .= " +PL_AM_V_${_} = \$(pl_am__v_${_}_\$(V)) +pl_am__v_${_}_ = \$(pl_am__v_${_}_\$(AM_DEFAULT_VERBOSITY)) +" for @special, map uc, @terse, @silent; + + #quoted plain text needs extra quotes + $ret .= " +PL_AM_V_BS_Text = \"\$(pl_am__v_BS_Text_\$(V))\" +pl_am__v_BS_Text_ = \$(pl_am__v_BS_Text_\$(AM_DEFAULT_VERBOSITY)) +" + #hide pm_to_blib output +. " +pl_am__v_BLIB_Hide_0 = \$(DEV_NULL) +pl_am__v_BLIB_Hide_1 = +" + #text for Mkbootstrap +. " +pl_am__v_BS_Text_0 = \"@{[_center('BS')]}\" +pl_am__v_BS_Text_1 = \"Running Mkbootstrap for\" +"; + #"terse" output + $ret .= " +pl_am__v_${_}_0 = \$(NOECHO)echo \"@{[_center($_)]}\" \$\@; +" for map uc, @terse; + + #no output + $ret .= " +pl_am__v_${_}_0 = \$(NOECHO) +" for map uc, @silent; + + #in verbose mode the "terse" echo expands to nothing + $ret .= " +pl_am__v_${_}_1 = +" for map uc, @terse, @silent; + $ret + } +}; +1; diff --git a/src/perl/common/Makefile.PL.in b/src/perl/common/Makefile.PL.in index 4e545e7c..84a80403 100644 --- a/src/perl/common/Makefile.PL.in +++ b/src/perl/common/Makefile.PL.in @@ -1,4 +1,4 @@ -use ExtUtils::MakeMaker; +use ExtUtils::MakeMaker;our $AM_DEFAULT_VERBOSITY='@AM_DEFAULT_VERBOSITY@';require "../Makefile_silent.pm"; WriteMakefile('NAME' => 'Irssi', 'LIBS' => '', diff --git a/src/perl/irc/Makefile.PL.in b/src/perl/irc/Makefile.PL.in index 8f1e94d5..0fbc5241 100644 --- a/src/perl/irc/Makefile.PL.in +++ b/src/perl/irc/Makefile.PL.in @@ -1,4 +1,4 @@ -use ExtUtils::MakeMaker; +use ExtUtils::MakeMaker;our $AM_DEFAULT_VERBOSITY='@AM_DEFAULT_VERBOSITY@';require "../Makefile_silent.pm"; WriteMakefile('NAME' => 'Irssi::Irc', 'LIBS' => '', diff --git a/src/perl/textui/Makefile.PL.in b/src/perl/textui/Makefile.PL.in index 9e80274b..3541f75c 100644 --- a/src/perl/textui/Makefile.PL.in +++ b/src/perl/textui/Makefile.PL.in @@ -1,4 +1,4 @@ -use ExtUtils::MakeMaker; +use ExtUtils::MakeMaker;our $AM_DEFAULT_VERBOSITY='@AM_DEFAULT_VERBOSITY@';require "../Makefile_silent.pm"; WriteMakefile('NAME' => 'Irssi::TextUI', 'LIBS' => '', diff --git a/src/perl/ui/Makefile.PL.in b/src/perl/ui/Makefile.PL.in index a349918e..ed87d528 100644 --- a/src/perl/ui/Makefile.PL.in +++ b/src/perl/ui/Makefile.PL.in @@ -1,4 +1,4 @@ -use ExtUtils::MakeMaker; +use ExtUtils::MakeMaker;our $AM_DEFAULT_VERBOSITY='@AM_DEFAULT_VERBOSITY@';require "../Makefile_silent.pm"; WriteMakefile('NAME' => 'Irssi::UI', 'LIBS' => '', From e0c8a9f3986249d8abde462bccdb00cd3d914ebc Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Sun, 5 Jun 2016 11:36:13 +0200 Subject: [PATCH 088/140] perl 5.10 fix --- src/perl/Makefile_silent.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/perl/Makefile_silent.pm b/src/perl/Makefile_silent.pm index e6036c98..372e4046 100644 --- a/src/perl/Makefile_silent.pm +++ b/src/perl/Makefile_silent.pm @@ -1,6 +1,6 @@ push @ExtUtils::MakeMaker::Overridable, qw(pm_to_blib); my $verb = $AM_DEFAULT_VERBOSITY; -package MY { +{ package MY; sub _center { my $z = shift; length $z == 2 ? " $z " : length $z == 4 ? " $z " : " $z " @@ -72,5 +72,5 @@ pl_am__v_${_}_1 = " for map uc, @terse, @silent; $ret } -}; +} 1; From bb190be0bfac956ada4f74a514ff70f28b114efa Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 13 Feb 2016 13:12:29 +0100 Subject: [PATCH 089/140] Replace mkpath with g_mkdir_with_parents --- src/core/log.c | 2 +- src/core/misc.c | 38 ------------------------------------- src/core/misc.h | 2 -- src/core/rawlog.c | 2 +- src/core/settings.c | 2 +- src/fe-common/core/fe-log.c | 2 +- 6 files changed, 4 insertions(+), 44 deletions(-) diff --git a/src/core/log.c b/src/core/log.c index 8306d2df..6af1effc 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -114,7 +114,7 @@ int log_start_logging(LOG_REC *log) /* path may contain variables (%time, $vars), make sure the directory is created */ dir = g_path_get_dirname(log->real_fname); - mkpath(dir, log_dir_create_mode); + g_mkdir_with_parents(dir, log_dir_create_mode); g_free(dir); } diff --git a/src/core/misc.c b/src/core/misc.c index c26610ec..a8a0975a 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -407,44 +407,6 @@ int regexp_match(const char *str, const char *regexp) #endif } -/* Create the directory and all it's parent directories */ -int mkpath(const char *path, int mode) -{ - struct stat statbuf; - const char *p; - char *dir; - - g_return_val_if_fail(path != NULL, -1); - - p = g_path_skip_root((char *) path); - if (p == NULL) { - /* not a full path, maybe not what we wanted - but continue anyway.. */ - p = path; - } - for (;;) { - if (*p != G_DIR_SEPARATOR && *p != '\0') { - p++; - continue; - } - - dir = g_strndup(path, (int) (p-path)); - if (stat(dir, &statbuf) != 0) { - if (mkdir(dir, mode) == -1) - { - g_free(dir); - return -1; - } - } - g_free(dir); - - if (*p++ == '\0') - break; - } - - return 0; -} - /* convert ~/ to $HOME */ char *convert_home(const char *path) { diff --git a/src/core/misc.h b/src/core/misc.h index 7e78d3b9..58b665bf 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -39,8 +39,6 @@ GSList *hashtable_get_keys(GHashTable *hash); /* easy way to check if regexp matches */ int regexp_match(const char *str, const char *regexp); -/* Create the directory and all it's parent directories */ -int mkpath(const char *path, int mode); /* convert ~/ to $HOME */ char *convert_home(const char *path); diff --git a/src/core/rawlog.c b/src/core/rawlog.c index 875c0ef2..2b46c50d 100644 --- a/src/core/rawlog.c +++ b/src/core/rawlog.c @@ -150,7 +150,7 @@ void rawlog_save(RAWLOG_REC *rawlog, const char *fname) int f; dir = g_path_get_dirname(fname); - mkpath(dir, log_dir_create_mode); + g_mkdir_with_parents(dir, log_dir_create_mode); g_free(dir); path = convert_home(fname); diff --git a/src/core/settings.c b/src/core/settings.c index 8e493124..17fc4115 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -683,7 +683,7 @@ static void init_configfile(void) if (stat(get_irssi_dir(), &statbuf) != 0) { /* ~/.irssi not found, create it. */ - if (mkpath(get_irssi_dir(), 0700) != 0) { + if (g_mkdir_with_parents(get_irssi_dir(), 0700) != 0) { g_error("Couldn't create %s directory", get_irssi_dir()); } } else if (!S_ISDIR(statbuf.st_mode)) { diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index f2c4c014..5bc5c4e1 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -453,7 +453,7 @@ static void autolog_open(SERVER_REC *server, const char *server_tag, log_item_add(log, LOG_ITEM_TARGET, target, server_tag); dir = g_path_get_dirname(log->real_fname); - mkpath(dir, log_dir_create_mode); + g_mkdir_with_parents(dir, log_dir_create_mode); g_free(dir); log->temp = TRUE; From 8289f360757870b56a15576a20e79e1f2ca30fef Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 13 Feb 2016 13:15:33 +0100 Subject: [PATCH 090/140] Check the return value of open() in rawlog.c --- src/core/rawlog.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/rawlog.c b/src/core/rawlog.c index 2b46c50d..5927e730 100644 --- a/src/core/rawlog.c +++ b/src/core/rawlog.c @@ -157,6 +157,11 @@ void rawlog_save(RAWLOG_REC *rawlog, const char *fname) f = open(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); g_free(path); + if (f < 0) { + g_warning("rawlog open() failed: %s", strerror(errno)); + return; + } + rawlog_dump(rawlog, f); close(f); } From 72712a0c62b0403f0fa472ccbe34fda8fb2cd530 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 13 Feb 2016 13:18:24 +0100 Subject: [PATCH 091/140] Replace strocpy with g_strlcpy The only difference was that the former returned 1 if the buffer was overflown, but the return value was never checked. --- src/core/misc.c | 14 -------------- src/core/misc.h | 3 --- src/irc/core/irc-nicklist.c | 2 +- src/irc/dcc/dcc-get.c | 6 +++--- 4 files changed, 4 insertions(+), 21 deletions(-) diff --git a/src/core/misc.c b/src/core/misc.c index a8a0975a..682d006c 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -773,20 +773,6 @@ char *escape_string(const char *str) return ret; } -int strocpy(char *dest, const char *src, size_t dstsize) -{ - if (dstsize == 0) - return -1; - - while (*src != '\0' && dstsize > 1) { - *dest++ = *src++; - dstsize--; - } - - *dest++ = '\0'; - return *src == '\0' ? 0 : -1; -} - int nearest_power(int num) { int n = 1; diff --git a/src/core/misc.h b/src/core/misc.h index 58b665bf..fdb16a49 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -83,9 +83,6 @@ int parse_size(const char *size, int *bytes); Stop when `end_char' is found from string. */ int is_numeric(const char *str, char end_char); -/* Like strlcpy(), but return -1 if buffer was overflown, 0 if not. */ -int strocpy(char *dest, const char *src, size_t dstsize); - /* strstr() with case-ignoring */ char *stristr(const char *data, const char *key); diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c index bcb9d1f6..b22f3269 100644 --- a/src/irc/core/irc-nicklist.c +++ b/src/irc/core/irc-nicklist.c @@ -48,7 +48,7 @@ NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick, rec->send_massjoin = send_massjoin; if (prefixes != NULL) { - strocpy(rec->prefixes, prefixes, sizeof(rec->prefixes)); + g_strlcpy(rec->prefixes, prefixes, sizeof(rec->prefixes)); } nicklist_insert(CHANNEL(channel), rec); diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c index ac281683..e7b796bb 100644 --- a/src/irc/dcc/dcc-get.c +++ b/src/irc/dcc/dcc-get.c @@ -473,8 +473,8 @@ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data, net_ip2host(&temp_dcc->addr, temp_dcc->addrstr); else { /* with IPv6, show it to us as it was sent */ - strocpy(temp_dcc->addrstr, address, - sizeof(temp_dcc->addrstr)); + g_strlcpy(temp_dcc->addrstr, address, + sizeof(temp_dcc->addrstr)); } /* This new signal is added to let us invoke @@ -508,7 +508,7 @@ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data, net_ip2host(&dcc->addr, dcc->addrstr); else { /* with IPv6, show it to us as it was sent */ - strocpy(dcc->addrstr, address, sizeof(dcc->addrstr)); + g_strlcpy(dcc->addrstr, address, sizeof(dcc->addrstr)); } dcc->port = port; dcc->size = size; From 7a3c6fe86ca55b4ef69b11443b87359b333bc20b Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 13 Feb 2016 14:16:05 +0100 Subject: [PATCH 092/140] Replace strarray_length with g_strv_length --- src/core/ignore.c | 2 +- src/core/misc.c | 14 -------------- src/core/misc.h | 2 -- src/core/special-vars.c | 2 +- src/fe-common/core/hilight-text.c | 2 +- src/irc/dcc/dcc-chat.c | 2 +- src/irc/dcc/dcc-get.c | 2 +- src/irc/dcc/dcc-resume.c | 2 +- src/irc/dcc/dcc-server.c | 2 +- 9 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/core/ignore.c b/src/core/ignore.c index 8d5a27c2..2047dc9d 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -241,7 +241,7 @@ IGNORE_REC *ignore_find_full(const char *servertag, const char *mask, const char if (channels == NULL || rec->channels == NULL) continue; /* other doesn't have channels */ - if (strarray_length(channels) != strarray_length(rec->channels)) + if (g_strv_length(channels) != g_strv_length(rec->channels)) continue; /* different amount of channels */ /* check that channels match */ diff --git a/src/core/misc.c b/src/core/misc.c index 682d006c..70d09e55 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -150,20 +150,6 @@ int find_substr(const char *list, const char *item) return FALSE; } -int strarray_length(char **array) -{ - int len; - - g_return_val_if_fail(array != NULL, 0); - - len = 0; - while (*array) { - len++; - array++; - } - return len; -} - int strarray_find(char **array, const char *item) { char **tmp; diff --git a/src/core/misc.h b/src/core/misc.h index fdb16a49..f8f1786f 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -102,8 +102,6 @@ char *show_lowascii(const char *str); /* replace all `from' chars in string to `to' chars. returns `str' */ char *replace_chars(char *str, char from, char to); -/* return how many items `array' has */ -int strarray_length(char **array); /* return index of `item' in `array' or -1 if not found */ int strarray_find(char **array, const char *item); diff --git a/src/core/special-vars.c b/src/core/special-vars.c index fe6bbed2..6ca080fc 100644 --- a/src/core/special-vars.c +++ b/src/core/special-vars.c @@ -44,7 +44,7 @@ static char *get_argument(char **cmd, char **arglist) arg = 0; max = -1; - argcount = arglist == NULL ? 0 : strarray_length(arglist); + argcount = arglist == NULL ? 0 : g_strv_length(arglist); if (**cmd == '*') { /* get all arguments */ diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 36e1e78c..4691a708 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -178,7 +178,7 @@ static HILIGHT_REC *hilight_find(const char *text, char **channels) if (channels == NULL || rec->channels == NULL) continue; /* other doesn't have channels */ - if (strarray_length(channels) != strarray_length(rec->channels)) + if (g_strv_length(channels) != g_strv_length(rec->channels)) continue; /* different amount of channels */ /* check that channels match */ diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c index e3dbe72d..ca90b8d8 100644 --- a/src/irc/dcc/dcc-chat.c +++ b/src/irc/dcc/dcc-chat.c @@ -619,7 +619,7 @@ static void ctcp_msg_dcc_chat(IRC_SERVER_REC *server, const char *data, /* CHAT
*/ /* CHAT
0 (DCC CHAT passive protocol) */ params = g_strsplit(data, " ", -1); - paramcount = strarray_length(params); + paramcount = g_strv_length(params); if (paramcount < 3) { g_strfreev(params); diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c index e7b796bb..f7a95bb9 100644 --- a/src/irc/dcc/dcc-get.c +++ b/src/irc/dcc/dcc-get.c @@ -423,7 +423,7 @@ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data, /* SEND
[...] */ /* SEND
0 (DCC SEND passive protocol) */ params = g_strsplit(data, " ", -1); - paramcount = strarray_length(params); + paramcount = g_strv_length(params); if (paramcount < 4) { signal_emit("dcc error ctcp", 5, "SEND", data, diff --git a/src/irc/dcc/dcc-resume.c b/src/irc/dcc/dcc-resume.c index 11b28aef..36f84ddf 100644 --- a/src/irc/dcc/dcc-resume.c +++ b/src/irc/dcc/dcc-resume.c @@ -88,7 +88,7 @@ static int dcc_ctcp_resume_parse(int type, const char *data, const char *nick, /* RESUME|ACCEPT */ /* RESUME|ACCEPT 0 (passive protocol) */ params = g_strsplit(data, " ", -1); - paramcount = strarray_length(params); + paramcount = g_strv_length(params); if (paramcount < 3) return 0; diff --git a/src/irc/dcc/dcc-server.c b/src/irc/dcc/dcc-server.c index 30224ff9..7ae572cd 100644 --- a/src/irc/dcc/dcc-server.c +++ b/src/irc/dcc/dcc-server.c @@ -245,7 +245,7 @@ static void dcc_server_msg(SERVER_DCC_REC *dcc, const char *msg) /* 120 clientnickname filesize filename */ params = g_strsplit(msg, " ", -1); - paramcount = strarray_length(params); + paramcount = g_strv_length(params); if (paramcount < 3) { g_strfreev(params); From 0f9d2b35700db69c66c5878b5562852565753dd2 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 13 Feb 2016 16:26:36 +0100 Subject: [PATCH 093/140] Remove unused regexp_match --- src/core/misc.c | 18 ------------------ src/core/misc.h | 3 --- 2 files changed, 21 deletions(-) diff --git a/src/core/misc.c b/src/core/misc.c index 70d09e55..48a49fa3 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -375,24 +375,6 @@ char *stristr_full(const char *data, const char *key) return strstr_full_case(data, key, TRUE); } -int regexp_match(const char *str, const char *regexp) -{ -#ifdef HAVE_REGEX_H - regex_t preg; - int ret; - - if (regcomp(&preg, regexp, REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0) - return 0; - - ret = regexec(&preg, str, 0, NULL, 0); - regfree(&preg); - - return ret == 0; -#else - return FALSE; -#endif -} - /* convert ~/ to $HOME */ char *convert_home(const char *path) { diff --git a/src/core/misc.h b/src/core/misc.h index f8f1786f..df17998f 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -36,9 +36,6 @@ char *gslist_to_string(GSList *list, const char *delimiter); items while using this list, use g_slist_free() after you're done with it */ GSList *hashtable_get_keys(GHashTable *hash); -/* easy way to check if regexp matches */ -int regexp_match(const char *str, const char *regexp); - /* convert ~/ to $HOME */ char *convert_home(const char *path); From e0b290c34fc116c043f51396e2770821ec357522 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 17 Feb 2016 23:21:38 +0100 Subject: [PATCH 094/140] Update the g_istr_hash function to use the djb hash --- src/core/misc.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/core/misc.c b/src/core/misc.c index 48a49fa3..74ca4725 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -401,22 +401,15 @@ int g_istr_cmp(gconstpointer v, gconstpointer v2) return g_ascii_strcasecmp((const char *) v, (const char *) v2); } -/* a char* hash function from ASU */ -unsigned int g_istr_hash(gconstpointer v) +guint g_istr_hash(gconstpointer v) { - const char *s = (const char *) v; - unsigned int h = 0, g; + const signed char *p; + guint32 h = 5381; - while (*s != '\0') { - h = (h << 4) + i_toupper(*s); - if ((g = h & 0xf0000000UL)) { - h = h ^ (g >> 24); - h = h ^ g; - } - s++; - } + for (p = v; *p != '\0'; p++) + h = (h << 5) + h + g_ascii_toupper(*p); - return h /* % M */; + return h; } /* Find `mask' from `data', you can use * and ? wildcards. */ From cc70e8c581713309c64eb15c3999341d17988e19 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 5 Jun 2016 16:48:27 +0200 Subject: [PATCH 095/140] Clean up some GTimeVal juggling --- src/irc/core/irc-servers.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 1df95f70..5b4af2ac 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -212,7 +212,6 @@ static void server_init(IRC_SERVER_REC *server) { IRC_SERVER_CONNECT_REC *conn; char *address, *ptr, *username, *cmd; - GTimeVal now; g_return_if_fail(server != NULL); @@ -287,9 +286,8 @@ static void server_init(IRC_SERVER_REC *server) /* prevent the queue from sending too early, we have a max cut off of 120 secs */ /* this will reset to 1 sec after we get the 001 event */ - g_get_current_time(&now); - memcpy(&((IRC_SERVER_REC *)server)->wait_cmd, &now, sizeof(GTimeVal)); - ((IRC_SERVER_REC *)server)->wait_cmd.tv_sec += 120; + g_get_current_time(&server->wait_cmd); + g_time_val_add(&server->wait_cmd, 120 * G_USEC_PER_SEC); } SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn) @@ -535,7 +533,7 @@ void irc_server_send_data(IRC_SERVER_REC *server, const char *data, int len) server->wait_cmd.tv_sec = 0; else { memcpy(&server->wait_cmd, &server->last_cmd, sizeof(GTimeVal)); - server->wait_cmd.tv_sec += 2 + len/100; + g_time_val_add(&server->wait_cmd, (2 + len/100) * G_USEC_PER_SEC); } } @@ -695,7 +693,6 @@ char *irc_server_get_channels(IRC_SERVER_REC *server) static void event_connected(IRC_SERVER_REC *server, const char *data, const char *from) { char *params, *nick; - GTimeVal now; g_return_if_fail(server != NULL); @@ -718,8 +715,7 @@ static void event_connected(IRC_SERVER_REC *server, const char *data, const char server->real_connect_time = time(NULL); /* let the queue send now that we are identified */ - g_get_current_time(&now); - memcpy(&server->wait_cmd, &now, sizeof(GTimeVal)); + g_get_current_time(&server->wait_cmd); if (server->connrec->usermode != NULL) { /* Send the user mode, before the autosendcmd. From 2e8744319d5e5e47799ec20b2f737c437e8c6398 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 5 Jun 2016 16:54:20 +0200 Subject: [PATCH 096/140] str_to_uofft is a tiny wrapper over strtoul{,l} --- src/core/misc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/core/misc.c b/src/core/misc.c index 74ca4725..9081abe1 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -515,15 +515,11 @@ int dec2octal(int decimal) /* string -> uoff_t */ uoff_t str_to_uofft(const char *str) { - uoff_t ret; - - ret = 0; - while (*str != '\0') { - ret = ret*10 + (*str - '0'); - str++; - } - - return ret; +#ifdef UOFF_T_LONG_LONG + return (uoff_t)strtoull(str, NULL, 10); +#else + return (uoff_t)strtoul(str, NULL, 10); +#endif } /* convert all low-ascii (<32) to ^ combinations */ From 0060f682c213dc25901f4c0ab01a01176e14da9e Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 5 Jun 2016 17:24:27 +0200 Subject: [PATCH 097/140] Factor out some redundant code and remove hashtable_get_keys --- src/core/misc.c | 22 ++++++++++++++++------ src/core/misc.h | 4 +--- src/core/servers.c | 16 +++------------- src/fe-common/core/fe-exec.c | 15 +++------------ src/fe-text/lastlog.c | 17 +++-------------- 5 files changed, 26 insertions(+), 48 deletions(-) diff --git a/src/core/misc.c b/src/core/misc.c index 9081abe1..bc9f504e 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -20,6 +20,7 @@ #include "module.h" #include "misc.h" +#include "commands.h" #ifdef HAVE_REGEX_H # include @@ -265,14 +266,23 @@ void hash_save_key(char *key, void *value, GSList **list) *list = g_slist_append(*list, key); } -/* save all keys in hash table to linked list - you shouldn't remove any - items while using this list, use g_slist_free() after you're done with it */ -GSList *hashtable_get_keys(GHashTable *hash) +/* remove all the options from the optlist hash table that are valid for the + * command cmd */ +GList *optlist_remove_known(const char *cmd, GHashTable *optlist) { - GSList *list; + GList *list, *tmp, *next; + + list = g_hash_table_get_keys(optlist); + if (cmd != NULL && list != NULL) { + for (tmp = list; tmp != NULL; tmp = next) { + char *option = tmp->data; + next = tmp->next; + + if (command_have_option(cmd, option)) + list = g_list_remove(list, option); + } + } - list = NULL; - g_hash_table_foreach(hash, (GHFunc) hash_save_key, &list); return list; } diff --git a/src/core/misc.h b/src/core/misc.h index df17998f..c095e131 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -32,9 +32,7 @@ char *gslistptr_to_string(GSList *list, int offset, const char *delimiter); /* `list' contains char* */ char *gslist_to_string(GSList *list, const char *delimiter); -/* save all keys in hash table to linked list - you shouldn't remove any - items while using this list, use g_slist_free() after you're done with it */ -GSList *hashtable_get_keys(GHashTable *hash); +GList *optlist_remove_known(const char *cmd, GHashTable *optlist); /* convert ~/ to $HOME */ char *convert_home(const char *path); diff --git a/src/core/servers.c b/src/core/servers.c index 3342304e..d6297c4d 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -684,21 +684,11 @@ SERVER_REC *cmd_options_get_server(const char *cmd, SERVER_REC *defserver) { SERVER_REC *server; - GSList *list, *tmp, *next; + GList *list; /* get all the options, then remove the known ones. there should be only one left - the server tag. */ - list = hashtable_get_keys(optlist); - if (cmd != NULL) { - for (tmp = list; tmp != NULL; tmp = next) { - char *option = tmp->data; - next = tmp->next; - - if (command_have_option(cmd, option)) - list = g_slist_remove(list, option); - } - } - + list = optlist_remove_known(cmd, optlist); if (list == NULL) return defserver; @@ -713,7 +703,7 @@ SERVER_REC *cmd_options_get_server(const char *cmd, server = NULL; } - g_slist_free(list); + g_list_free(list); return server; } diff --git a/src/fe-common/core/fe-exec.c b/src/fe-common/core/fe-exec.c index b5f289ce..36990866 100644 --- a/src/fe-common/core/fe-exec.c +++ b/src/fe-common/core/fe-exec.c @@ -237,22 +237,13 @@ static int signal_name_to_id(const char *name) static int cmd_options_get_signal(const char *cmd, GHashTable *optlist) { - GSList *list, *tmp, *next; + GList *list; char *signame; int signum; /* get all the options, then remove the known ones. there should be only one left - the signal */ - list = hashtable_get_keys(optlist); - if (cmd != NULL) { - for (tmp = list; tmp != NULL; tmp = next) { - char *option = tmp->data; - next = tmp->next; - - if (command_have_option(cmd, option)) - list = g_slist_remove(list, option); - } - } + list = optlist_remove_known(cmd, optlist); if (list == NULL) return -1; @@ -272,7 +263,7 @@ static int cmd_options_get_signal(const char *cmd, return -2; } - g_slist_free(list); + g_list_free(list); return signum; } diff --git a/src/fe-text/lastlog.c b/src/fe-text/lastlog.c index 166d2847..c0b1dde8 100644 --- a/src/fe-text/lastlog.c +++ b/src/fe-text/lastlog.c @@ -39,21 +39,10 @@ Returns -1 if unknown option was given. */ int cmd_options_get_level(const char *cmd, GHashTable *optlist) { - GSList *list, *tmp, *next; + GList *list; int level, retlevel; - /* get all the options, then remove the known ones. there should - be only one left - the server tag. */ - list = hashtable_get_keys(optlist); - if (cmd != NULL) { - for (tmp = list; tmp != NULL; tmp = next) { - char *option = tmp->data; - next = tmp->next; - - if (command_have_option(cmd, option)) - list = g_slist_remove(list, option); - } - } + list = optlist_remove_known(cmd, optlist); retlevel = 0; while (list != NULL) { @@ -68,7 +57,7 @@ int cmd_options_get_level(const char *cmd, GHashTable *optlist) } retlevel |= level; - list = g_slist_remove(list, list->data); + list = g_list_remove(list, list->data); } return retlevel; From 98fce5f8074abcf5d35a1834952e42cd79384db2 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 5 Jun 2016 22:47:04 +0200 Subject: [PATCH 098/140] Deprecate net_connect() --- src/core/network.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/network.h b/src/core/network.h index fb627b4d..03f3b813 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -37,7 +37,7 @@ GIOChannel *g_io_channel_new(int handle); int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ -GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); +GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) G_GNUC_DEPRECATED; /* Connect to socket with ip address and SSL*/ GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); From 9fd286fed8d231f9c78353f5d746ed82e3bc05c4 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 5 Jun 2016 22:47:29 +0200 Subject: [PATCH 099/140] Bump the ABI --- src/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.h b/src/common.h index 66892b78..0a7b72f0 100644 --- a/src/common.h +++ b/src/common.h @@ -6,7 +6,7 @@ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ -#define IRSSI_ABI_VERSION 5 +#define IRSSI_ABI_VERSION 6 #define DEFAULT_SERVER_ADD_PORT 6667 From d6d74c0da981af22fb8cbfa68d3bdc5446c55155 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Mon, 6 Jun 2016 16:58:40 +0200 Subject: [PATCH 100/140] Do not crash on OPTCHAN when item has no server May fix bugs.debian.org#826525 --- src/core/commands.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/commands.c b/src/core/commands.c index 88d1208c..607baf77 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -666,7 +666,7 @@ get_optional_channel(WI_ITEM_REC *active_item, char **data, int require_name) const char *ret; char *tmp, *origtmp, *channel; - if (active_item == NULL) { + if (active_item == NULL || active_item->server == NULL) { /* no active channel in window, channel required */ return cmd_get_param(data); } @@ -674,11 +674,13 @@ get_optional_channel(WI_ITEM_REC *active_item, char **data, int require_name) origtmp = tmp = g_strdup(*data); channel = cmd_get_param(&tmp); - if (g_strcmp0(channel, "*") == 0 && !require_name) { + if (g_strcmp0(channel, "*") == 0 && IS_CHANNEL(active_item) && + !require_name) { /* "*" means active channel */ cmd_get_param(data); ret = window_item_get_target(active_item); - } else if (!server_ischannel(active_item->server, channel)) { + } else if (IS_CHANNEL(active_item) && + !server_ischannel(active_item->server, channel)) { /* we don't have channel parameter - use active channel */ ret = window_item_get_target(active_item); } else { From bf9d9494db89e7de45653e4797e2977c6e185c13 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 12 Jun 2016 15:26:07 +0200 Subject: [PATCH 101/140] Add a CHOICE type to the settings system. This is useful to let the user choose an option between a finite set of valid alternatives. --- src/core/settings.c | 95 ++++++++++++++++++++++++++++---- src/core/settings.h | 14 ++++- src/fe-common/core/completion.c | 17 +++++- src/fe-common/core/fe-settings.c | 5 ++ 4 files changed, 113 insertions(+), 18 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index 8e493124..9c2389bc 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -148,11 +148,34 @@ int settings_get_size(const char *key) return str == NULL ? 0 : bytes; } +int settings_get_choice(const char *key) +{ + SETTINGS_REC *rec; + CONFIG_NODE *node; + char *str; + int idx; + + rec = settings_get(key, SETTING_TYPE_CHOICE); + if (rec == NULL) return -1; + + node = iconfig_node_traverse("settings", FALSE); + node = node == NULL ? NULL : iconfig_node_section(node, rec->module, -1); + + str = node == NULL ? rec->default_value.v_string : + config_node_get_str(node, key, rec->default_value.v_string); + + idx = strarray_find(rec->choices, str); + return (idx < 0) ? rec->default_value.v_int : idx; +} + char *settings_get_print(SETTINGS_REC *rec) { char *value = NULL; switch(rec->type) { + case SETTING_TYPE_CHOICE: + value = g_strdup(rec->choices[settings_get_choice(rec->key)]); + break; case SETTING_TYPE_BOOLEAN: value = g_strdup(settings_get_bool(rec->key) ? "ON" : "OFF"); break; @@ -172,13 +195,31 @@ char *settings_get_print(SETTINGS_REC *rec) static void settings_add(const char *module, const char *section, const char *key, SettingType type, - const SettingValue *default_value) + const SettingValue *default_value, + const char *choices) { SETTINGS_REC *rec; + char **choices_vec = NULL; g_return_if_fail(key != NULL); g_return_if_fail(section != NULL); + if (type == SETTING_TYPE_CHOICE) { + if (choices == NULL) { + g_warning("Trying to add setting '%s' with no choices.", key); + return; + } + + choices_vec = g_strsplit(choices, ",", -1); + + /* validate the default value */ + if (default_value->v_int < 0 || default_value->v_int >= g_strv_length(choices_vec)) { + g_warning("Trying to add setting '%s' with an invalid default value.", key); + g_strfreev(choices_vec); + return; + } + } + rec = g_hash_table_lookup(settings, key); if (rec != NULL) { /* Already exists, make sure it's correct type */ @@ -197,6 +238,7 @@ static void settings_add(const char *module, const char *section, rec->type = type; rec->default_value = *default_value; + rec->choices = choices_vec; g_hash_table_insert(settings, rec->key, rec); } } @@ -208,7 +250,17 @@ void settings_add_str_module(const char *module, const char *section, memset(&default_value, 0, sizeof(default_value)); default_value.v_string = g_strdup(def); - settings_add(module, section, key, SETTING_TYPE_STRING, &default_value); + settings_add(module, section, key, SETTING_TYPE_STRING, &default_value, NULL); +} + +void settings_add_choice_module(const char *module, const char *section, + const char *key, int def, const char *choices) +{ + SettingValue default_value; + + memset(&default_value, 0, sizeof(default_value)); + default_value.v_int = def; + settings_add(module, section, key, SETTING_TYPE_CHOICE, &default_value, choices); } void settings_add_int_module(const char *module, const char *section, @@ -218,7 +270,7 @@ void settings_add_int_module(const char *module, const char *section, memset(&default_value, 0, sizeof(default_value)); default_value.v_int = def; - settings_add(module, section, key, SETTING_TYPE_INT, &default_value); + settings_add(module, section, key, SETTING_TYPE_INT, &default_value, NULL); } void settings_add_bool_module(const char *module, const char *section, @@ -228,8 +280,7 @@ void settings_add_bool_module(const char *module, const char *section, memset(&default_value, 0, sizeof(default_value)); default_value.v_bool = def; - settings_add(module, section, key, SETTING_TYPE_BOOLEAN, - &default_value); + settings_add(module, section, key, SETTING_TYPE_BOOLEAN, &default_value, NULL); } void settings_add_time_module(const char *module, const char *section, @@ -239,7 +290,7 @@ void settings_add_time_module(const char *module, const char *section, memset(&default_value, 0, sizeof(default_value)); default_value.v_string = g_strdup(def); - settings_add(module, section, key, SETTING_TYPE_TIME, &default_value); + settings_add(module, section, key, SETTING_TYPE_TIME, &default_value, NULL); } void settings_add_level_module(const char *module, const char *section, @@ -249,7 +300,7 @@ void settings_add_level_module(const char *module, const char *section, memset(&default_value, 0, sizeof(default_value)); default_value.v_string = g_strdup(def); - settings_add(module, section, key, SETTING_TYPE_LEVEL, &default_value); + settings_add(module, section, key, SETTING_TYPE_LEVEL, &default_value, NULL); } void settings_add_size_module(const char *module, const char *section, @@ -259,14 +310,16 @@ void settings_add_size_module(const char *module, const char *section, memset(&default_value, 0, sizeof(default_value)); default_value.v_string = g_strdup(def); - settings_add(module, section, key, SETTING_TYPE_SIZE, &default_value); + settings_add(module, section, key, SETTING_TYPE_SIZE, &default_value, NULL); } static void settings_destroy(SETTINGS_REC *rec) { if (rec->type != SETTING_TYPE_INT && - rec->type != SETTING_TYPE_BOOLEAN) + rec->type != SETTING_TYPE_BOOLEAN && + rec->type != SETTING_TYPE_CHOICE) g_free(rec->default_value.v_string); + g_strfreev(rec->choices); g_free(rec->module); g_free(rec->section); g_free(rec->key); @@ -328,6 +381,24 @@ static CONFIG_NODE *settings_get_node(const char *key) return iconfig_node_section(node, rec->module, NODE_TYPE_BLOCK); } +gboolean settings_set_choice(const char *key, const char *value) +{ + SETTINGS_REC *rec; + + rec = settings_get_record(key); + /* XXX: The leading/trailing whitespace makes the test fail */ + if (rec != NULL && g_strv_contains((const char **)rec->choices, value) == FALSE) { + char *msg = g_strjoinv(",", rec->choices); + g_warning("Invalid value for '%s', must be one of: %s", key, msg); + g_free(msg); + + return FALSE; + } + + settings_set_str(key, value); + return TRUE; +} + void settings_set_str(const char *key, const char *value) { iconfig_node_set_str(settings_get_node(key), key, value); @@ -343,7 +414,7 @@ void settings_set_bool(const char *key, int value) iconfig_node_set_bool(settings_get_node(key), key, value); } -int settings_set_time(const char *key, const char *value) +gboolean settings_set_time(const char *key, const char *value) { int msecs; @@ -354,7 +425,7 @@ int settings_set_time(const char *key, const char *value) return TRUE; } -int settings_set_level(const char *key, const char *value) +gboolean settings_set_level(const char *key, const char *value) { int iserror; @@ -366,7 +437,7 @@ int settings_set_level(const char *key, const char *value) return TRUE; } -int settings_set_size(const char *key, const char *value) +gboolean settings_set_size(const char *key, const char *value) { int size; diff --git a/src/core/settings.h b/src/core/settings.h index 6f2cf129..d174f250 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -8,6 +8,7 @@ typedef enum { SETTING_TYPE_TIME, SETTING_TYPE_LEVEL, SETTING_TYPE_SIZE, + SETTING_TYPE_CHOICE, SETTING_TYPE_ANY } SettingType; @@ -26,6 +27,7 @@ typedef struct { SettingType type; SettingValue default_value; + char **choices; } SETTINGS_REC; /* macros for handling the default Irssi configuration */ @@ -58,6 +60,7 @@ int settings_get_bool(const char *key); int settings_get_time(const char *key); /* as milliseconds */ int settings_get_level(const char *key); int settings_get_size(const char *key); /* as bytes */ +int settings_get_choice(const char *key); char *settings_get_print(SETTINGS_REC *rec); /* Functions to add/remove settings */ @@ -73,6 +76,8 @@ void settings_add_level_module(const char *module, const char *section, const char *key, const char *def); void settings_add_size_module(const char *module, const char *section, const char *key, const char *def); +void settings_add_choice_module(const char *module, const char *section, + const char *key, int def, const char *choices); void settings_remove(const char *key); void settings_remove_module(const char *module); @@ -88,13 +93,16 @@ void settings_remove_module(const char *module); settings_add_level_module(MODULE_NAME, section, key, def) #define settings_add_size(section, key, def) \ settings_add_size_module(MODULE_NAME, section, key, def) +#define settings_add_choice(section, key, def, choices) \ + settings_add_choice_module(MODULE_NAME, section, key, def, choices) void settings_set_str(const char *key, const char *value); void settings_set_int(const char *key, int value); void settings_set_bool(const char *key, int value); -int settings_set_time(const char *key, const char *value); -int settings_set_level(const char *key, const char *value); -int settings_set_size(const char *key, const char *value); +gboolean settings_set_time(const char *key, const char *value); +gboolean settings_set_level(const char *key, const char *value); +gboolean settings_set_size(const char *key, const char *value); +gboolean settings_set_choice(const char *key, const char *value); /* Get the type (SETTING_TYPE_xxx) of `key' */ SettingType settings_get_type(const char *key); diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index 861054b5..0e9982d5 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -690,9 +690,20 @@ static void sig_complete_set(GList **list, WINDOW_REC *window, else if (*line != '\0' && *word == '\0') { SETTINGS_REC *rec = settings_get_record(line); if (rec != NULL) { - char *value = settings_get_print(rec); - if (value != NULL) - *list = g_list_append(*list, value); + /* show the whole list of valid options */ + if (rec->type == SETTING_TYPE_CHOICE) { + char **tmp = rec->choices; + + while (*tmp) + *list = g_list_append(*list, g_strdup(*tmp++)); + } + /* show the current option */ + else { + char *value = settings_get_print(rec); + + if (value != NULL) + *list = g_list_append(*list, value); + } } } diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index b689cbf9..e25886ec 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -142,6 +142,11 @@ static void cmd_set(char *data) else set_int(key, value); break; + case SETTING_TYPE_CHOICE: + settings_set_choice(key, clear ? "" : + set_default ? rec->choices[rec->default_value.v_int] : + value); + break; case SETTING_TYPE_STRING: settings_set_str(key, clear ? "" : set_default ? rec->default_value.v_string : From 86c5e56ef41c70030e43d03b4c01e2df8188c30b Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 12 Jun 2016 16:26:18 +0200 Subject: [PATCH 102/140] Make rejoin_channels_mode of type CHOICE --- src/irc/core/irc-servers.c | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 1df95f70..6f5803ed 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -623,39 +623,25 @@ char *irc_server_get_channels(IRC_SERVER_REC *server) GString *chans, *keys; char *ret; int use_keys; - char *rejoin_channels_mode; + int rejoin_channels_mode; g_return_val_if_fail(server != NULL, FALSE); - rejoin_channels_mode = g_strdup(settings_get_str("rejoin_channels_on_reconnect")); + rejoin_channels_mode = settings_get_choice("rejoin_channels_on_reconnect"); - if (rejoin_channels_mode == NULL || - (g_ascii_strcasecmp(rejoin_channels_mode, "on") != 0 && - g_ascii_strcasecmp(rejoin_channels_mode, "off") != 0 && - g_ascii_strcasecmp(rejoin_channels_mode, "auto") != 0)) { - g_warning("Invalid value for 'rejoin_channels_on_reconnect', valid values are 'on', 'off', 'auto', using 'on' as default value."); - g_free(rejoin_channels_mode); - rejoin_channels_mode = g_strdup("on"); - } + /* do we want to rejoin channels in the first place? */ + if(rejoin_channels_mode == 0) + return g_strdup(""); chans = g_string_new(NULL); keys = g_string_new(NULL); use_keys = FALSE; - /* do we want to rejoin channels in the first place? */ - if(g_ascii_strcasecmp(rejoin_channels_mode, "off") == 0) { - g_string_free(chans, TRUE); - g_string_free(keys, TRUE); - g_free(rejoin_channels_mode); - return g_strdup(""); - } - /* get currently joined channels */ for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { CHANNEL_REC *channel = tmp->data; CHANNEL_SETUP_REC *setup = channel_setup_find(channel->name, channel->server->connrec->chatnet); - if ((setup != NULL && setup->autojoin && g_ascii_strcasecmp(rejoin_channels_mode, "auto") == 0) || - g_ascii_strcasecmp(rejoin_channels_mode, "on") == 0) { + if ((setup != NULL && setup->autojoin && rejoin_channels_mode == 2) || rejoin_channels_mode == 1) { g_string_append_printf(chans, "%s,", channel->name); g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" : channel->key); if (channel->key != NULL) @@ -668,8 +654,7 @@ char *irc_server_get_channels(IRC_SERVER_REC *server) REJOIN_REC *rec = tmp->data; CHANNEL_SETUP_REC *setup = channel_setup_find(rec->channel, server->tag); - if ((setup != NULL && setup->autojoin && g_ascii_strcasecmp(rejoin_channels_mode, "auto") == 0) || - g_ascii_strcasecmp(rejoin_channels_mode, "on") == 0) { + if ((setup != NULL && setup->autojoin && rejoin_channels_mode == 2) || rejoin_channels_mode == 1) { g_string_append_printf(chans, "%s,", rec->channel); g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" : rec->key); @@ -687,7 +672,6 @@ char *irc_server_get_channels(IRC_SERVER_REC *server) ret = chans->str; g_string_free(chans, FALSE); g_string_free(keys, TRUE); - g_free(rejoin_channels_mode); return ret; } @@ -1033,7 +1017,7 @@ void irc_server_init_isupport(IRC_SERVER_REC *server) void irc_servers_init(void) { - settings_add_str("servers", "rejoin_channels_on_reconnect", "on"); + settings_add_choice("servers", "rejoin_channels_on_reconnect", 1, "off,on,auto"); settings_add_str("misc", "usermode", DEFAULT_USER_MODE); settings_add_str("misc", "split_line_start", ""); settings_add_str("misc", "split_line_end", ""); From 31f12c10df52e44e7cef0245fc55ae38159ce9e3 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 12 Jun 2016 16:38:34 +0200 Subject: [PATCH 103/140] Use strarray_find instead of g_strv_contains --- src/core/settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/settings.c b/src/core/settings.c index 9c2389bc..9871ad30 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -387,7 +387,7 @@ gboolean settings_set_choice(const char *key, const char *value) rec = settings_get_record(key); /* XXX: The leading/trailing whitespace makes the test fail */ - if (rec != NULL && g_strv_contains((const char **)rec->choices, value) == FALSE) { + if (rec != NULL && strarray_find(rec->choices, value) < 0) { char *msg = g_strjoinv(",", rec->choices); g_warning("Invalid value for '%s', must be one of: %s", key, msg); g_free(msg); From 7307b48bd6928207ded9e186af3f3b97625f00bb Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 12 Jun 2016 22:58:35 +0200 Subject: [PATCH 104/140] Sort the completion results Make sure the current option is shown first. --- src/fe-common/core/completion.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index 0e9982d5..c87fdb50 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -690,19 +690,20 @@ static void sig_complete_set(GList **list, WINDOW_REC *window, else if (*line != '\0' && *word == '\0') { SETTINGS_REC *rec = settings_get_record(line); if (rec != NULL) { + char *value = settings_get_print(rec); + + /* show the current option first */ + if (value != NULL) + *list = g_list_append(*list, value); + /* show the whole list of valid options */ if (rec->type == SETTING_TYPE_CHOICE) { - char **tmp = rec->choices; + char **tmp; - while (*tmp) - *list = g_list_append(*list, g_strdup(*tmp++)); - } - /* show the current option */ - else { - char *value = settings_get_print(rec); - - if (value != NULL) - *list = g_list_append(*list, value); + for (tmp = rec->choices; *tmp; tmp++) { + if (g_ascii_strcasecmp(*tmp, value) != 0) + *list = g_list_append(*list, g_strdup(*tmp)); + } } } } From 6f795f020d5c374023dc9ca647b267aef0a76950 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 12 Jun 2016 23:39:22 +0200 Subject: [PATCH 105/140] Strip the surrounding whitespace. --- src/core/settings.c | 2 +- src/fe-common/core/fe-settings.c | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index 9871ad30..8509a9ff 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -386,7 +386,7 @@ gboolean settings_set_choice(const char *key, const char *value) SETTINGS_REC *rec; rec = settings_get_record(key); - /* XXX: The leading/trailing whitespace makes the test fail */ + if (rec != NULL && strarray_find(rec->choices, value) < 0) { char *msg = g_strjoinv(",", rec->choices); g_warning("Invalid value for '%s', must be one of: %s", key, msg); diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index e25886ec..ca1f871d 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -67,6 +67,7 @@ static void set_print_pattern(const char *pattern) static void set_boolean(const char *key, const char *value) { char *stripped_value; + stripped_value = g_strdup(value); g_strstrip(stripped_value); @@ -79,7 +80,7 @@ static void set_boolean(const char *key, const char *value) else printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_NOT_TOGGLE); - g_free(stripped_value); + g_free(stripped_value); } static void set_int(const char *key, const char *value) @@ -99,6 +100,16 @@ static void set_int(const char *key, const char *value) settings_set_int(key, (int)longval); } +static void set_choice(const char *key, const char *value) +{ + char *stripped_value; + + stripped_value = g_strdup(value); + g_strstrip(stripped_value); + settings_set_choice(key, stripped_value); + g_free(stripped_value); +} + /* SYNTAX: SET [-clear | -default] [ []] */ static void cmd_set(char *data) { @@ -143,9 +154,10 @@ static void cmd_set(char *data) set_int(key, value); break; case SETTING_TYPE_CHOICE: - settings_set_choice(key, clear ? "" : - set_default ? rec->choices[rec->default_value.v_int] : - value); + if (clear || set_default) + settings_set_choice(key, rec->choices[rec->default_value.v_int]); + else + set_choice(key, value); break; case SETTING_TYPE_STRING: settings_set_str(key, clear ? "" : From 9ea155f8df5fe9b3d67e8729f611b87a0c2a82c9 Mon Sep 17 00:00:00 2001 From: dequis Date: Sun, 12 Jun 2016 20:28:06 -0300 Subject: [PATCH 106/140] servers-reconnect: pass unix_socket attribute to new connection Trying to /reconnect unix sockets turned them into inet. --- src/core/servers-reconnect.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index f419035b..58c9dd09 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -190,6 +190,7 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info) dest->away_reason = g_strdup(src->away_reason); dest->no_autojoin_channels = src->no_autojoin_channels; dest->no_autosendcmd = src->no_autosendcmd; + dest->unix_socket = src->unix_socket; dest->use_ssl = src->use_ssl; dest->ssl_cert = g_strdup(src->ssl_cert); From 9a30ab53df226acb4586a2f214f3994a7b8b32ea Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 13 Jun 2016 14:03:00 +0200 Subject: [PATCH 107/140] Move the validation of the CHOICE setting value Also, use a FORMAT to show the error message. --- src/core/settings.c | 8 ++------ src/fe-common/core/fe-settings.c | 10 +++++++++- src/fe-common/core/module-formats.c | 1 + src/fe-common/core/module-formats.h | 1 + 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index 8509a9ff..0716103a 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -387,15 +387,11 @@ gboolean settings_set_choice(const char *key, const char *value) rec = settings_get_record(key); - if (rec != NULL && strarray_find(rec->choices, value) < 0) { - char *msg = g_strjoinv(",", rec->choices); - g_warning("Invalid value for '%s', must be one of: %s", key, msg); - g_free(msg); - + if (rec != NULL && strarray_find(rec->choices, value) < 0) return FALSE; - } settings_set_str(key, value); + return TRUE; } diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index ca1f871d..6f69d930 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -106,7 +106,15 @@ static void set_choice(const char *key, const char *value) stripped_value = g_strdup(value); g_strstrip(stripped_value); - settings_set_choice(key, stripped_value); + + if (settings_set_choice(key, stripped_value) == FALSE) { + SETTINGS_REC *rec = settings_get_record(key); + char *msg = g_strjoinv(",", rec->choices); + + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_INVALID_CHOICE, msg); + g_free(msg); + } + g_free(stripped_value); } diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index b897b0c6..5c07f14c 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -221,6 +221,7 @@ FORMAT_REC fecommon_core_formats[] = { { "invalid_level", "Invalid message level", 0 }, { "invalid_size", "Invalid size", 0 }, { "invalid_charset", "Invalid charset: $0", 1, { 0 } }, + { "invalid_choice", "Invalid choice, must be one of $0", 1, { 0 } }, { "eval_max_recurse", "/eval hit maximum recursion limit", 0 }, { "program_not_found", "Could not find file or file is not executable", 0 }, { "no_server_defined", "No servers defined for this network, see /help server for how to add one", 0 }, diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h index de1e13f2..2b45ff6b 100644 --- a/src/fe-common/core/module-formats.h +++ b/src/fe-common/core/module-formats.h @@ -190,6 +190,7 @@ enum { TXT_INVALID_LEVEL, TXT_INVALID_SIZE, TXT_INVALID_CHARSET, + TXT_INVALID_CHOICE, TXT_EVAL_MAX_RECURSE, TXT_PROGRAM_NOT_FOUND, TXT_NO_SERVER_DEFINED, From 439e21f12746519d36e205a3ac053c882d67c024 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 13 Jun 2016 14:07:04 +0200 Subject: [PATCH 108/140] Use ; as separator instead of , --- src/core/settings.c | 2 +- src/irc/core/irc-servers.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index 0716103a..e6b5d16f 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -210,7 +210,7 @@ static void settings_add(const char *module, const char *section, return; } - choices_vec = g_strsplit(choices, ",", -1); + choices_vec = g_strsplit(choices, ";", -1); /* validate the default value */ if (default_value->v_int < 0 || default_value->v_int >= g_strv_length(choices_vec)) { diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 6f5803ed..c8ba0a48 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -1017,7 +1017,7 @@ void irc_server_init_isupport(IRC_SERVER_REC *server) void irc_servers_init(void) { - settings_add_choice("servers", "rejoin_channels_on_reconnect", 1, "off,on,auto"); + settings_add_choice("servers", "rejoin_channels_on_reconnect", 1, "off;on;auto"); settings_add_str("misc", "usermode", DEFAULT_USER_MODE); settings_add_str("misc", "split_line_start", ""); settings_add_str("misc", "split_line_end", ""); From 5c8423a08cd9ffbe3363f3b0e5722e4a32157914 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 13 Jun 2016 20:27:37 +0200 Subject: [PATCH 109/140] Add a space after the comma when listing the options. --- src/fe-common/core/fe-settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index 6f69d930..abbd45a8 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -109,7 +109,7 @@ static void set_choice(const char *key, const char *value) if (settings_set_choice(key, stripped_value) == FALSE) { SETTINGS_REC *rec = settings_get_record(key); - char *msg = g_strjoinv(",", rec->choices); + char *msg = g_strjoinv(", ", rec->choices); printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_INVALID_CHOICE, msg); g_free(msg); From 78c1c1518a7382628368b09f8744189edf3ceef3 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 6 Jun 2016 22:25:32 +0200 Subject: [PATCH 110/140] Be smart about case-matching the nicks. If the prefix contains an uppercase letter then don't use the case-insensitive search functions. --- src/fe-common/core/chat-completion.c | 38 +++++++++++++++++++++------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c index c37c77cd..b212de5f 100644 --- a/src/fe-common/core/chat-completion.c +++ b/src/fe-common/core/chat-completion.c @@ -52,6 +52,18 @@ static int completion_auto, completion_strict; last_msg_add(&((MODULE_CHANNEL_REC *) MODULE_DATA(channel))->lastmsgs, \ nick, own, keep_publics_count) +static int contains_uppercase(const char *s1) +{ + const char *ch; + + for (ch = s1; *ch != '\0'; ch++) { + if (g_ascii_isupper(*ch)) + return TRUE; + } + + return FALSE; +} + static LAST_MSG_REC *last_msg_find(GSList *list, const char *nick) { while (list != NULL) { @@ -336,7 +348,8 @@ GList *completion_msg(SERVER_REC *win_server, } static void complete_from_nicklist(GList **outlist, CHANNEL_REC *channel, - const char *nick, const char *suffix) + const char *nick, const char *suffix, + const int match_case) { MODULE_CHANNEL_REC *mchannel; GSList *tmp; @@ -352,8 +365,10 @@ static void complete_from_nicklist(GList **outlist, CHANNEL_REC *channel, for (tmp = mchannel->lastmsgs; tmp != NULL; tmp = tmp->next) { LAST_MSG_REC *rec = tmp->data; - if (g_ascii_strncasecmp(rec->nick, nick, len) == 0 && - glist_find_icase_string(*outlist, rec->nick) == NULL) { + if ((match_case? strncmp(rec->nick, nick, len) + : g_ascii_strncasecmp(rec->nick, nick, len)) == 0 && + (match_case? glist_find_string(*outlist, rec->nick) + : glist_find_icase_string(*outlist, rec->nick)) == NULL) { str = g_strconcat(rec->nick, suffix, NULL); if (completion_lowercase) ascii_strdown(str); if (rec->own) @@ -368,7 +383,8 @@ static void complete_from_nicklist(GList **outlist, CHANNEL_REC *channel, static GList *completion_nicks_nonstrict(CHANNEL_REC *channel, const char *nick, - const char *suffix) + const char *suffix, + const int match_case) { GSList *nicks, *tmp; GList *list; @@ -404,7 +420,8 @@ static GList *completion_nicks_nonstrict(CHANNEL_REC *channel, *out = '\0'; /* add to list if 'cleaned' nick matches */ - if (g_ascii_strncasecmp(str, nick, len) == 0) { + if ((match_case? strncmp(str, nick, len) + : g_ascii_strncasecmp(str, nick, len)) == 0) { tnick = g_strconcat(rec->nick, suffix, NULL); if (completion_lowercase) ascii_strdown(tnick); @@ -428,7 +445,7 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick, GSList *nicks, *tmp; GList *list; char *str; - int len; + int len, match_case; g_return_val_if_fail(channel != NULL, NULL); g_return_val_if_fail(nick != NULL, NULL); @@ -437,9 +454,11 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick, if (suffix != NULL && *suffix == '\0') suffix = NULL; + match_case = contains_uppercase(nick); + /* put first the nicks who have recently said something */ list = NULL; - complete_from_nicklist(&list, channel, nick, suffix); + complete_from_nicklist(&list, channel, nick, suffix, match_case); /* and add the rest of the nicks too */ len = strlen(nick); @@ -447,7 +466,8 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick, for (tmp = nicks; tmp != NULL; tmp = tmp->next) { NICK_REC *rec = tmp->data; - if (g_ascii_strncasecmp(rec->nick, nick, len) == 0 && + if ((match_case? strncmp(rec->nick, nick, len) + : g_ascii_strncasecmp(rec->nick, nick, len)) == 0 && rec != channel->ownnick) { str = g_strconcat(rec->nick, suffix, NULL); if (completion_lowercase) @@ -463,7 +483,7 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick, /* remove non alphanum chars from nick and search again in case list is still NULL ("foo" would match "_foo_" f.e.) */ if (!completion_strict) - list = g_list_concat(list, completion_nicks_nonstrict(channel, nick, suffix)); + list = g_list_concat(list, completion_nicks_nonstrict(channel, nick, suffix, match_case)); return list; } From 862729d7a39be25aee3524a52e19f9735dec6e1f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 7 Jun 2016 15:45:39 +0200 Subject: [PATCH 111/140] Add a completion_match_case setting. --- src/fe-common/core/chat-completion.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c index b212de5f..3e144602 100644 --- a/src/fe-common/core/chat-completion.c +++ b/src/fe-common/core/chat-completion.c @@ -38,11 +38,18 @@ #include "chat-completion.h" #include "window-items.h" +enum { + COMPLETE_MCASE_NEVER = 0, + COMPLETE_MCASE_ALWAYS, + COMPLETE_MCASE_AUTO, +}; + static int keep_privates_count, keep_publics_count; static int completion_lowercase; static char *completion_char, *cmdchars; static GSList *global_lastmsgs; static int completion_auto, completion_strict; +static int completion_match_case; #define SERVER_LAST_MSG_ADD(server, nick) \ last_msg_add(&((MODULE_SERVER_REC *) MODULE_DATA(server))->lastmsgs, \ @@ -52,7 +59,7 @@ static int completion_auto, completion_strict; last_msg_add(&((MODULE_CHANNEL_REC *) MODULE_DATA(channel))->lastmsgs, \ nick, own, keep_publics_count) -static int contains_uppercase(const char *s1) +static gboolean contains_uppercase(const char *s1) { const char *ch; @@ -454,7 +461,8 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick, if (suffix != NULL && *suffix == '\0') suffix = NULL; - match_case = contains_uppercase(nick); + match_case = completion_match_case == COMPLETE_MCASE_ALWAYS || + (completion_match_case == COMPLETE_MCASE_AUTO && contains_uppercase(nick)); /* put first the nicks who have recently said something */ list = NULL; @@ -1150,6 +1158,8 @@ static void read_settings(void) completion_auto = settings_get_bool("completion_auto"); completion_strict = settings_get_bool("completion_strict"); + completion_match_case = settings_get_choice("completion_nicks_match_case"); + g_free_not_null(completion_char); completion_char = g_strdup(settings_get_str("completion_char")); @@ -1170,6 +1180,7 @@ void chat_completion_init(void) settings_add_int("completion", "completion_keep_privates", 10); settings_add_bool("completion", "completion_nicks_lowercase", FALSE); settings_add_bool("completion", "completion_strict", FALSE); + settings_add_choice("completion", "completion_nicks_match_case", COMPLETE_MCASE_AUTO, "never;always;auto"); settings_add_bool("lookandfeel", "expand_escapes", FALSE); From 2da49e3ca6357b65e31fb494b2edb0d22e73c62c Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 13 Jun 2016 22:14:08 +0200 Subject: [PATCH 112/140] Don't crash when the key isn't found. --- src/core/settings.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index e6b5d16f..1242293d 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -153,7 +153,7 @@ int settings_get_choice(const char *key) SETTINGS_REC *rec; CONFIG_NODE *node; char *str; - int idx; + int index; rec = settings_get(key, SETTING_TYPE_CHOICE); if (rec == NULL) return -1; @@ -164,8 +164,10 @@ int settings_get_choice(const char *key) str = node == NULL ? rec->default_value.v_string : config_node_get_str(node, key, rec->default_value.v_string); - idx = strarray_find(rec->choices, str); - return (idx < 0) ? rec->default_value.v_int : idx; + if (str == NULL || (index = strarray_find(rec->choices, str)) < 0) + return rec->default_value.v_int; + + return index; } char *settings_get_print(SETTINGS_REC *rec) From 77ad62fadbcd9d5ce33889417de0099e035d8ddc Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Thu, 16 Jun 2016 21:30:46 +0200 Subject: [PATCH 113/140] completion fixes --- src/fe-common/core/completion.c | 56 ++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index c87fdb50..46fd9db7 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -37,8 +37,11 @@ static int last_want_space, last_line_pos; #define isseparator_notspace(c) \ ((c) == ',') +#define isseparator_space(c) \ + ((c) == ' ') + #define isseparator(c) \ - ((c) == ' ' || isseparator_notspace(c)) + (isseparator_space(c) || isseparator_notspace(c)) void chat_completion_init(void); void chat_completion_deinit(void); @@ -153,20 +156,23 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i word = NULL; linestart = NULL; } else { + char* old_wordstart; + /* get the word we want to complete */ word = get_word_at(line, *pos, &wordstart); + old_wordstart = wordstart; + startpos = (int) (wordstart-line); wordlen = strlen(word); - /* get the start of line until the word we're completing */ - if (isseparator(*line)) { - /* empty space at the start of line */ - if (wordstart == line) - wordstart += strlen(wordstart); - } else { - while (wordstart > line && isseparator(wordstart[-1])) - wordstart--; - } + /* remove trailing spaces from linestart */ + while (wordstart > line && isseparator_space(wordstart[-1])) + wordstart--; + + /* unless everything was spaces */ + if (old_wordstart > line && wordstart == line) + wordstart = old_wordstart - 1; + linestart = g_strndup(line, (int) (wordstart-line)); /* completions usually add space after the word, that makes @@ -175,19 +181,24 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i BUT if we start completion with "/msg ", we don't want to complete the /msg word, but instead complete empty word with /msg being in linestart. */ - if (!erase && *pos > 0 && line[*pos-1] == ' ' && - (*linestart == '\0' || wordstart[-1] != ' ')) { + if (!erase && *pos > 0 && isseparator_space(line[*pos-1]) && + (*linestart == '\0' || !isseparator_space(wordstart[-1]))) { char *old; - old = linestart; + old = linestart; linestart = *linestart == '\0' ? g_strdup(word) : - g_strconcat(linestart, " ", word, NULL); + g_strdup_printf("%s%c%s", + /* do not accidentally duplicate the word separator */ + line == wordstart - 1 ? "" : linestart, + wordstart[-1], word); g_free(old); g_free(word); word = g_strdup(""); - startpos = strlen(linestart)+1; + + startpos = *linestart == '\0' ? 0 : + strlen(linestart)+1; wordlen = 0; } @@ -397,7 +408,8 @@ static GList *completion_get_aliases(const char *alias, char cmdchar) continue; if (g_ascii_strncasecmp(node->key, alias, len) == 0) { - word = g_strdup_printf("%c%s", cmdchar, node->key); + word = cmdchar == '\0' ? g_strdup(node->key) : + g_strdup_printf("%c%s", cmdchar, node->key); /* add matching alias to completion list, aliases will be appended after command completions and kept in uppercase to show it's an alias */ @@ -589,13 +601,19 @@ static void sig_complete_word(GList **list, WINDOW_REC *window, /* command completion? */ cmdchars = settings_get_str("cmdchars"); - if (*word != '\0' && *linestart == '\0' && strchr(cmdchars, *word)) { + if (*word != '\0' && ((*linestart == '\0' && strchr(cmdchars, *word)) || + (*linestart != '\0' && linestart[1] == '\0' && + strchr(cmdchars, *linestart)))) { + gboolean skip = *linestart == '\0' ? TRUE : FALSE; + /* complete /command */ - *list = completion_get_commands(word+1, *word); + *list = completion_get_commands(word + (skip ? 1 : 0), + skip ? *word : '\0'); /* complete aliases, too */ *list = g_list_concat(*list, - completion_get_aliases(word+1, *word)); + completion_get_aliases(word + (skip ? 1 : 0), + skip ? *word : '\0')); if (*list != NULL) signal_stop(); return; From 92a2384ab06c542c8f6a3d0f80a54892d74dc649 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sat, 18 Jun 2016 17:51:58 +0200 Subject: [PATCH 114/140] Add /channel modify --- src/fe-common/core/fe-channels.c | 38 +++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index 046d641a..fe8e4807 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -246,9 +246,7 @@ static void cmd_channel(const char *data, SERVER_REC *server, WI_ITEM_REC *item) } } -/* SYNTAX: CHANNEL ADD [-auto | -noauto] [-bots ] [-botcmd ] - [] */ -static void cmd_channel_add(const char *data) +static void cmd_channel_add_modify(const char *data, gboolean add) { GHashTable *optlist; CHATNET_REC *chatnetrec; @@ -257,18 +255,19 @@ static void cmd_channel_add(const char *data) void *free_arg; if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS, - "channel add", &optlist, &channel, &chatnet, &password)) + "channel add", &optlist, &channel, &chatnet, &password)) return; - if (*chatnet == '\0' || *channel == '\0') + if (*chatnet == '\0' || *channel == '\0') { cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + } chatnetrec = chatnet_find(chatnet); if (chatnetrec == NULL) { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, - TXT_UNKNOWN_CHATNET, chatnet); + TXT_UNKNOWN_CHATNET, chatnet); cmd_params_free(free_arg); - return; + return; } botarg = g_hash_table_lookup(optlist, "bots"); @@ -276,10 +275,17 @@ static void cmd_channel_add(const char *data) rec = channel_setup_find(channel, chatnet); if (rec == NULL) { + if (!add) { + cmd_params_free(free_arg); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + TXT_CHANSETUP_NOT_FOUND, channel, chatnet); + return; + } + rec = CHAT_PROTOCOL(chatnetrec)->create_channel_setup(); rec->name = g_strdup(channel); rec->chatnet = g_strdup(chatnet); - } else { + } else if (!add) { if (g_hash_table_lookup(optlist, "bots")) g_free_and_null(rec->botmasks); if (g_hash_table_lookup(optlist, "botcmd")) g_free_and_null(rec->autosendcmd); if (*password != '\0') g_free_and_null(rec->password); @@ -299,6 +305,20 @@ static void cmd_channel_add(const char *data) cmd_params_free(free_arg); } +/* SYNTAX: CHANNEL ADD [-auto | -noauto] [-bots ] [-botcmd ] + [] */ +static void cmd_channel_add(const char *data) +{ + cmd_channel_add_modify(data, 1); +} + +/* SYNTAX: CHANNEL MODIFY [-auto | -noauto] [-bots ] [-botcmd ] + [] */ +static void cmd_channel_modify(const char *data) +{ + cmd_channel_add_modify(data, 0); +} + /* SYNTAX: CHANNEL REMOVE */ static void cmd_channel_remove(const char *data) { @@ -622,6 +642,7 @@ void fe_channels_init(void) command_bind("join", NULL, (SIGNAL_FUNC) cmd_join); command_bind("channel", NULL, (SIGNAL_FUNC) cmd_channel); command_bind("channel add", NULL, (SIGNAL_FUNC) cmd_channel_add); + command_bind("channel modify", NULL, (SIGNAL_FUNC) cmd_channel_modify); command_bind("channel remove", NULL, (SIGNAL_FUNC) cmd_channel_remove); command_bind("channel list", NULL, (SIGNAL_FUNC) cmd_channel_list); command_bind("names", NULL, (SIGNAL_FUNC) cmd_names); @@ -643,6 +664,7 @@ void fe_channels_deinit(void) command_unbind("join", (SIGNAL_FUNC) cmd_join); command_unbind("channel", (SIGNAL_FUNC) cmd_channel); command_unbind("channel add", (SIGNAL_FUNC) cmd_channel_add); + command_unbind("channel modify", (SIGNAL_FUNC) cmd_channel_modify); command_unbind("channel remove", (SIGNAL_FUNC) cmd_channel_remove); command_unbind("channel list", (SIGNAL_FUNC) cmd_channel_list); command_unbind("names", (SIGNAL_FUNC) cmd_names); From 1dd1dde1d46439dac17bb7f053f2665ed31a4a5e Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sat, 18 Jun 2016 17:52:26 +0200 Subject: [PATCH 115/140] Add /server modify --- src/fe-common/core/fe-server.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index 429e6dac..f3792b47 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -104,7 +104,7 @@ static SERVER_SETUP_REC *create_server_setup(GHashTable *optlist) return server; } -static void cmd_server_add(const char *data) +static void cmd_server_add_modify(const char *data, gboolean add) { GHashTable *optlist; SERVER_SETUP_REC *rec; @@ -113,7 +113,7 @@ static void cmd_server_add(const char *data) int port; if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS, - "server add", &optlist, &addr, &portstr, &password)) + "server add", &optlist, &addr, &portstr, &password)) return; if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -124,6 +124,13 @@ static void cmd_server_add(const char *data) rec = server_setup_find(addr, port, chatnet); if (rec == NULL) { + if (!add) { + cmd_params_free(free_arg); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + TXT_SETUPSERVER_NOT_FOUND, addr, port); + return; + } + rec = create_server_setup(optlist); if (rec == NULL) { cmd_params_free(free_arg); @@ -131,7 +138,7 @@ static void cmd_server_add(const char *data) } rec->address = g_strdup(addr); rec->port = port; - } else { + } else if (!add) { value = g_hash_table_lookup(optlist, "port"); if (value != NULL && *value != '\0') rec->port = atoi(value); @@ -205,6 +212,16 @@ static void cmd_server_add(const char *data) cmd_params_free(free_arg); } +static void cmd_server_add(const char *data) +{ + cmd_server_add_modify(data, 1); +} + +static void cmd_server_modify(const char *data) +{ + cmd_server_add_modify(data, 0); +} + /* SYNTAX: SERVER REMOVE
[] [] */ static void cmd_server_remove(const char *data) { @@ -388,6 +405,7 @@ void fe_server_init(void) command_bind("server", NULL, (SIGNAL_FUNC) cmd_server); command_bind("server connect", NULL, (SIGNAL_FUNC) cmd_server_connect); command_bind("server add", NULL, (SIGNAL_FUNC) cmd_server_add); + command_bind("server modify", NULL, (SIGNAL_FUNC) cmd_server_modify); command_bind("server remove", NULL, (SIGNAL_FUNC) cmd_server_remove); command_bind_first("server", NULL, (SIGNAL_FUNC) server_command); command_bind_first("disconnect", NULL, (SIGNAL_FUNC) server_command); @@ -412,6 +430,7 @@ void fe_server_deinit(void) command_unbind("server", (SIGNAL_FUNC) cmd_server); command_unbind("server connect", (SIGNAL_FUNC) cmd_server_connect); command_unbind("server add", (SIGNAL_FUNC) cmd_server_add); + command_unbind("server modify", (SIGNAL_FUNC) cmd_server_modify); command_unbind("server remove", (SIGNAL_FUNC) cmd_server_remove); command_unbind("server", (SIGNAL_FUNC) server_command); command_unbind("disconnect", (SIGNAL_FUNC) server_command); From 421288cf5066267b60580af2b6ae511c46570bf0 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sat, 18 Jun 2016 17:52:47 +0200 Subject: [PATCH 116/140] Add /network modify --- src/fe-common/irc/fe-ircnet.c | 47 +++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index 4d7037d5..90697bba 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -88,14 +88,7 @@ static void cmd_network_list(void) printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_NETWORK_FOOTER); } -/* SYNTAX: NETWORK ADD [-nick ] [-user ] [-realname ] - [-host ] [-usermode ] [-autosendcmd ] - [-querychans ] [-whois ] [-msgs ] - [-kicks ] [-modes ] [-cmdspeed ] - [-cmdmax ] [-sasl_mechanism ] - [-sasl_username ] [-sasl_password ] - */ -static void cmd_network_add(const char *data) +static void cmd_network_add_modify(const char *data, gboolean add) { GHashTable *optlist; char *name, *value; @@ -103,15 +96,23 @@ static void cmd_network_add(const char *data) IRC_CHATNET_REC *rec; if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS, - "network add", &optlist, &name)) + "network add", &optlist, &name)) return; + if (*name == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); rec = ircnet_find(name); if (rec == NULL) { + if (!add) { + cmd_params_free(free_arg); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + IRCTXT_NETWORK_NOT_FOUND, name); + return; + } + rec = g_new0(IRC_CHATNET_REC, 1); rec->name = g_strdup(name); - } else { + } else if (!add) { if (g_hash_table_lookup(optlist, "nick")) g_free_and_null(rec->nick); if (g_hash_table_lookup(optlist, "user")) g_free_and_null(rec->username); if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname); @@ -174,6 +175,30 @@ static void cmd_network_add(const char *data) cmd_params_free(free_arg); } +/* SYNTAX: NETWORK ADD [-nick ] [-user ] [-realname ] + [-host ] [-usermode ] [-autosendcmd ] + [-querychans ] [-whois ] [-msgs ] + [-kicks ] [-modes ] [-cmdspeed ] + [-cmdmax ] [-sasl_mechanism ] + [-sasl_username ] [-sasl_password ] + */ +static void cmd_network_add(const char *data) +{ + cmd_network_add_modify(data, 1); +} + +/* SYNTAX: NETWORK MODIFY [-nick ] [-user ] [-realname ] + [-host ] [-usermode ] [-autosendcmd ] + [-querychans ] [-whois ] [-msgs ] + [-kicks ] [-modes ] [-cmdspeed ] + [-cmdmax ] [-sasl_mechanism ] + [-sasl_username ] [-sasl_password ] + */ +static void cmd_network_modify(const char *data) +{ + cmd_network_add_modify(data, 0); +} + /* SYNTAX: NETWORK REMOVE */ static void cmd_network_remove(const char *data) { @@ -206,6 +231,7 @@ void fe_ircnet_init(void) command_bind("network", NULL, (SIGNAL_FUNC) cmd_network); command_bind("network list", NULL, (SIGNAL_FUNC) cmd_network_list); command_bind("network add", NULL, (SIGNAL_FUNC) cmd_network_add); + command_bind("network modify", NULL, (SIGNAL_FUNC) cmd_network_modify); command_bind("network remove", NULL, (SIGNAL_FUNC) cmd_network_remove); command_set_options("network add", "-kicks -msgs -modes -whois -cmdspeed " @@ -218,5 +244,6 @@ void fe_ircnet_deinit(void) command_unbind("network", (SIGNAL_FUNC) cmd_network); command_unbind("network list", (SIGNAL_FUNC) cmd_network_list); command_unbind("network add", (SIGNAL_FUNC) cmd_network_add); + command_unbind("network modify", (SIGNAL_FUNC) cmd_network_modify); command_unbind("network remove", (SIGNAL_FUNC) cmd_network_remove); } From 1d2113a6387d70caa399cb3311b15203d2d99fda Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sat, 18 Jun 2016 17:53:35 +0200 Subject: [PATCH 117/140] Add /server modify SYNTAX --- src/fe-common/irc/fe-irc-server.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/fe-common/irc/fe-irc-server.c b/src/fe-common/irc/fe-irc-server.c index 2cb99a2f..360fe212 100644 --- a/src/fe-common/irc/fe-irc-server.c +++ b/src/fe-common/irc/fe-irc-server.c @@ -50,12 +50,19 @@ const char *get_visible_target(IRC_SERVER_REC *server, const char *target) return target; } + /* SYNTAX: SERVER ADD [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] [-ssl_ciphers ] [-auto | -noauto] [-network ] [-host ] [-cmdspeed ] [-cmdmax ] [-port ]
[ []] */ +/* SYNTAX: SERVER MODIFY [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] + [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] + [-ssl_ciphers ] + [-auto | -noauto] [-network ] [-host ] + [-cmdspeed ] [-cmdmax ] [-port ] +
[ []] */ /* NOTE: -network replaces the old -ircnet flag. */ static void sig_server_add_fill(IRC_SERVER_SETUP_REC *rec, GHashTable *optlist) From 054a98b0ac9bd7f828cd0878687d53e01a3438da Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sat, 18 Jun 2016 17:59:59 +0200 Subject: [PATCH 118/140] Add info about MODIFY to help files --- docs/help/in/channel.in | 2 ++ docs/help/in/network.in | 2 ++ docs/help/in/server.in | 2 ++ 3 files changed, 6 insertions(+) diff --git a/docs/help/in/channel.in b/docs/help/in/channel.in index 01bea3c1..86e824c2 100644 --- a/docs/help/in/channel.in +++ b/docs/help/in/channel.in @@ -7,6 +7,7 @@ LIST: Displays the list of configured channels. ADD: Adds a channel to your configuration. + MODIFY: Modifies a channel in your configuration. REMOVE: Removes a channel from your configuration. -auto: Automatically join the channel. @@ -36,6 +37,7 @@ /CHANNEL ADD -auto #basementcat Quakenet secret_lair /CHANNEL ADD -auto -bots '*!@*.irssi.org *!bot@irssi.org' -botcmd 'msg $0 op WzerTrzq' #hideout Freenode /CHANNEL ADD -auto -bots 'Q!TheQBot@CServe.quakenet.org' -botcmd '^MSG Q op #irssi' #irssi Quakenet + /CHANNEL MODIFY -noauto #irssi Freenode /CHANNEL REMOVE #hideout Freenode %9Special Example:%9 diff --git a/docs/help/in/network.in b/docs/help/in/network.in index 2918f6ae..ba08ef69 100644 --- a/docs/help/in/network.in +++ b/docs/help/in/network.in @@ -7,6 +7,7 @@ LIST: Displays the list of configured networks. ADD: Adds a network to your configuration. + MODIFY: Modifies a network in your configuration. REMOVE: Removes a network from your configuration. -nick: Specifies the nickname to use. @@ -59,6 +60,7 @@ /NETWORK ADD -usermode +iw -nick mike -realname 'The one and only mike!' -host staff.irssi.org Freenode /NETWORK ADD -autosendcmd '^MSG NickServ identify WzerT8zq' Freenode /NETWORK ADD -autosendcmd '^MSG Q@CServe.quakenet.org AUTH mike WzerT8zq; WAIT 2000; OPER mike WzerT8zq; WAIT 2000; MODE mike +kXP' Quakenet + /NETWORK MODIFY -usermode +gi EFnet /NETWORK REMOVE Freenode %9See also:%9 CHANNEL, CONNECT, SERVER diff --git a/docs/help/in/server.in b/docs/help/in/server.in index e407b6a9..68a62e2d 100644 --- a/docs/help/in/server.in +++ b/docs/help/in/server.in @@ -8,6 +8,7 @@ LIST: Displays the list of servers you are connected to. CONNECT: Connects to the given server. ADD: Adds a server to your configuration. + MODIFY: Modifies a server in your configuration. REMOVE: Removes a server from your configuration. PURGE: Purges the commands queued to be sent to the server. @@ -62,6 +63,7 @@ /SERVER CONNECT +chat.freenode.net /SERVER ADD -network Freenode -noautosendcmd orwell.freenode.net /SERVER ADD -! -auto -host staff.irssi.org -port 6667 -4 -network Freenode -noproxy orwell.freenode.net + /SERVER MODIFY -network Freenode -noauto orwell.freenode.net /SERVER REMOVE orwell.freenode.net 6667 Freenode /SERVER PURGE /SERVER PURGE orwell.freenode.net From 79e30405e6b22b116d9d2c8ac5af0f4a4dfdc9c7 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sat, 18 Jun 2016 18:02:04 +0200 Subject: [PATCH 119/140] Let ADD still work as modify --- src/fe-common/core/fe-channels.c | 2 +- src/fe-common/core/fe-server.c | 2 +- src/fe-common/irc/fe-ircnet.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index fe8e4807..b79938eb 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -285,7 +285,7 @@ static void cmd_channel_add_modify(const char *data, gboolean add) rec = CHAT_PROTOCOL(chatnetrec)->create_channel_setup(); rec->name = g_strdup(channel); rec->chatnet = g_strdup(chatnet); - } else if (!add) { + } else { if (g_hash_table_lookup(optlist, "bots")) g_free_and_null(rec->botmasks); if (g_hash_table_lookup(optlist, "botcmd")) g_free_and_null(rec->autosendcmd); if (*password != '\0') g_free_and_null(rec->password); diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index f3792b47..e0f05980 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -138,7 +138,7 @@ static void cmd_server_add_modify(const char *data, gboolean add) } rec->address = g_strdup(addr); rec->port = port; - } else if (!add) { + } else { value = g_hash_table_lookup(optlist, "port"); if (value != NULL && *value != '\0') rec->port = atoi(value); diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index 90697bba..6778cb02 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -112,7 +112,7 @@ static void cmd_network_add_modify(const char *data, gboolean add) rec = g_new0(IRC_CHATNET_REC, 1); rec->name = g_strdup(name); - } else if (!add) { + } else { if (g_hash_table_lookup(optlist, "nick")) g_free_and_null(rec->nick); if (g_hash_table_lookup(optlist, "user")) g_free_and_null(rec->username); if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname); From 4292dbd20250faa4736ab9871bddd97dd7d6c80a Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sat, 18 Jun 2016 18:47:11 +0200 Subject: [PATCH 120/140] Add command_set_options for modify commands to allow completion --- src/fe-common/core/fe-channels.c | 1 + src/fe-common/core/fe-server.c | 1 + src/fe-common/irc/fe-ircnet.c | 2 ++ 3 files changed, 4 insertions(+) diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index b79938eb..dc7d1ee7 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -649,6 +649,7 @@ void fe_channels_init(void) command_bind("cycle", NULL, (SIGNAL_FUNC) cmd_cycle); command_set_options("channel add", "auto noauto -bots -botcmd"); + command_set_options("channel modify", "auto noauto -bots -botcmd"); command_set_options("names", "count ops halfops voices normal"); command_set_options("join", "invite window"); } diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index e0f05980..827b237e 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -410,6 +410,7 @@ void fe_server_init(void) command_bind_first("server", NULL, (SIGNAL_FUNC) server_command); command_bind_first("disconnect", NULL, (SIGNAL_FUNC) server_command); command_set_options("server add", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +ssl_ciphers auto noauto proxy noproxy -host -port noautosendcmd"); + command_set_options("server modify", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +ssl_ciphers auto noauto proxy noproxy -host -port noautosendcmd"); signal_add("server looking", (SIGNAL_FUNC) sig_server_looking); signal_add("server connecting", (SIGNAL_FUNC) sig_server_connecting); diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index 6778cb02..e82fa27f 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -236,6 +236,8 @@ void fe_ircnet_init(void) command_set_options("network add", "-kicks -msgs -modes -whois -cmdspeed " "-cmdmax -nick -user -realname -host -autosendcmd -querychans -usermode -sasl_mechanism -sasl_username -sasl_password"); + command_set_options("network modify", "-kicks -msgs -modes -whois -cmdspeed " + "-cmdmax -nick -user -realname -host -autosendcmd -querychans -usermode -sasl_mechanism -sasl_username -sasl_password"); } void fe_ircnet_deinit(void) From 2bb913f0c128dbb37737b7c2d7af99ed70801993 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sun, 19 Jun 2016 16:35:13 +0200 Subject: [PATCH 121/140] Fix minor nits --- src/fe-common/core/fe-channels.c | 10 ++++------ src/fe-common/core/fe-server.c | 4 ++-- src/fe-common/irc/fe-irc-server.c | 18 ++++++------------ src/fe-common/irc/fe-ircnet.c | 25 +++++++++---------------- 4 files changed, 21 insertions(+), 36 deletions(-) diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index dc7d1ee7..2802e933 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -305,18 +305,16 @@ static void cmd_channel_add_modify(const char *data, gboolean add) cmd_params_free(free_arg); } -/* SYNTAX: CHANNEL ADD [-auto | -noauto] [-bots ] [-botcmd ] - [] */ +/* SYNTAX: CHANNEL ADD|MODIFY [-auto | -noauto] [-bots ] [-botcmd ] + [] */ static void cmd_channel_add(const char *data) { - cmd_channel_add_modify(data, 1); + cmd_channel_add_modify(data, TRUE); } -/* SYNTAX: CHANNEL MODIFY [-auto | -noauto] [-bots ] [-botcmd ] - [] */ static void cmd_channel_modify(const char *data) { - cmd_channel_add_modify(data, 0); + cmd_channel_add_modify(data, FALSE); } /* SYNTAX: CHANNEL REMOVE */ diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index 827b237e..d6f2841b 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -214,12 +214,12 @@ static void cmd_server_add_modify(const char *data, gboolean add) static void cmd_server_add(const char *data) { - cmd_server_add_modify(data, 1); + cmd_server_add_modify(data, TRUE); } static void cmd_server_modify(const char *data) { - cmd_server_add_modify(data, 0); + cmd_server_add_modify(data, FALSE); } /* SYNTAX: SERVER REMOVE
[] [] */ diff --git a/src/fe-common/irc/fe-irc-server.c b/src/fe-common/irc/fe-irc-server.c index 360fe212..2e22d6f2 100644 --- a/src/fe-common/irc/fe-irc-server.c +++ b/src/fe-common/irc/fe-irc-server.c @@ -51,18 +51,12 @@ const char *get_visible_target(IRC_SERVER_REC *server, const char *target) return target; } -/* SYNTAX: SERVER ADD [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] - [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] - [-ssl_ciphers ] - [-auto | -noauto] [-network ] [-host ] - [-cmdspeed ] [-cmdmax ] [-port ] -
[ []] */ -/* SYNTAX: SERVER MODIFY [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] - [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] - [-ssl_ciphers ] - [-auto | -noauto] [-network ] [-host ] - [-cmdspeed ] [-cmdmax ] [-port ] -
[ []] */ +/* SYNTAX: SERVER ADD|MODIFY [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] + [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] + [-ssl_ciphers ] + [-auto | -noauto] [-network ] [-host ] + [-cmdspeed ] [-cmdmax ] [-port ] +
[ []] */ /* NOTE: -network replaces the old -ircnet flag. */ static void sig_server_add_fill(IRC_SERVER_SETUP_REC *rec, GHashTable *optlist) diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index e82fa27f..b2605379 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -175,28 +175,21 @@ static void cmd_network_add_modify(const char *data, gboolean add) cmd_params_free(free_arg); } -/* SYNTAX: NETWORK ADD [-nick ] [-user ] [-realname ] - [-host ] [-usermode ] [-autosendcmd ] - [-querychans ] [-whois ] [-msgs ] - [-kicks ] [-modes ] [-cmdspeed ] - [-cmdmax ] [-sasl_mechanism ] - [-sasl_username ] [-sasl_password ] - */ +/* SYNTAX: NETWORK ADD|MODIFY [-nick ] [-user ] [-realname ] + [-host ] [-usermode ] [-autosendcmd ] + [-querychans ] [-whois ] [-msgs ] + [-kicks ] [-modes ] [-cmdspeed ] + [-cmdmax ] [-sasl_mechanism ] + [-sasl_username ] [-sasl_password ] + */ static void cmd_network_add(const char *data) { - cmd_network_add_modify(data, 1); + cmd_network_add_modify(data, TRUE); } -/* SYNTAX: NETWORK MODIFY [-nick ] [-user ] [-realname ] - [-host ] [-usermode ] [-autosendcmd ] - [-querychans ] [-whois ] [-msgs ] - [-kicks ] [-modes ] [-cmdspeed ] - [-cmdmax ] [-sasl_mechanism ] - [-sasl_username ] [-sasl_password ] - */ static void cmd_network_modify(const char *data) { - cmd_network_add_modify(data, 0); + cmd_network_add_modify(data, FALSE); } /* SYNTAX: NETWORK REMOVE */ From a4223a3b2e5f5689c61633542f05e70c28226717 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Tue, 21 Jun 2016 22:05:21 +0200 Subject: [PATCH 122/140] use TRUE/FALSE in if statements for gboolean --- src/fe-common/core/fe-channels.c | 2 +- src/fe-common/core/fe-server.c | 2 +- src/fe-common/irc/fe-ircnet.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index 2802e933..532b1bf8 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -275,7 +275,7 @@ static void cmd_channel_add_modify(const char *data, gboolean add) rec = channel_setup_find(channel, chatnet); if (rec == NULL) { - if (!add) { + if (add == FALSE) { cmd_params_free(free_arg); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CHANSETUP_NOT_FOUND, channel, chatnet); diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index d6f2841b..468cb707 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -124,7 +124,7 @@ static void cmd_server_add_modify(const char *data, gboolean add) rec = server_setup_find(addr, port, chatnet); if (rec == NULL) { - if (!add) { + if (add == FALSE) { cmd_params_free(free_arg); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_SETUPSERVER_NOT_FOUND, addr, port); diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index b2605379..b70a9ea7 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -103,7 +103,7 @@ static void cmd_network_add_modify(const char *data, gboolean add) rec = ircnet_find(name); if (rec == NULL) { - if (!add) { + if (add == FALSE) { cmd_params_free(free_arg); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NETWORK_NOT_FOUND, name); From c2c32e39559e4081ea2ebfecbfc67d9553a9ad12 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Sat, 25 Jun 2016 16:06:50 +0200 Subject: [PATCH 123/140] check for NULL in statusbar_more_updated fixes crash due to invalid access of active_win members when the more indicator is triggered without an active window --- src/fe-text/statusbar-items.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/fe-text/statusbar-items.c b/src/fe-text/statusbar-items.c index e3e0c2a6..0db4f63a 100644 --- a/src/fe-text/statusbar-items.c +++ b/src/fe-text/statusbar-items.c @@ -289,6 +289,10 @@ static void sig_statusbar_more_updated(void) { int visible; + /* no active window, for example during /window hide */ + if (active_win == NULL) + return; + visible = g_slist_find(more_visible, WINDOW_MAIN(active_win)) != NULL; if (WINDOW_GUI(active_win)->view->more_text != visible) statusbar_items_redraw("more"); From 9559a8ead9048433783a453ca47c63514a39b205 Mon Sep 17 00:00:00 2001 From: Tom Feist Date: Tue, 12 Jul 2016 12:42:15 +0200 Subject: [PATCH 124/140] Allow Irssi::signal_remove to work properly with coderefs --- src/perl/perl-signals.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/perl/perl-signals.c b/src/perl/perl-signals.c index 007f7ad5..8f993660 100644 --- a/src/perl/perl-signals.c +++ b/src/perl/perl-signals.c @@ -433,8 +433,9 @@ static void perl_signal_remove_list_one(GSList **siglist, PERL_SIGNAL_REC *rec) } #define sv_func_cmp(f1, f2) \ - (f1 == f2 || (SvPOK(f1) && SvPOK(f2) && \ - g_strcmp0(SvPV_nolen(f1), SvPV_nolen(f2)) == 0)) + ((SvROK(f1) && SvROK(f2) && SvRV(f1) == SvRV(f2)) || \ + (SvPOK(f1) && SvPOK(f2) && \ + g_strcmp0(SvPV_nolen(f1), SvPV_nolen(f2)) == 0)) static void perl_signal_remove_list(GSList **list, SV *func) { From 0fe81cae83f1b981e6544be6fcaa924f2ce7caad Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 12 Jul 2016 15:46:36 +0200 Subject: [PATCH 125/140] Correct the prototype for the 'message private' signal. --- docs/signals.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/signals.txt b/docs/signals.txt index 8b71fd95..5e03d901 100644 --- a/docs/signals.txt +++ b/docs/signals.txt @@ -260,7 +260,7 @@ fe-exec.c: fe-messages.c: "message public", SERVER_REC, char *msg, char *nick, char *address, char *target - "message private", SERVER_REC, char *msg, char *nick, char *address + "message private", SERVER_REC, char *msg, char *nick, char *address, char *target "message own_public", SERVER_REC, char *msg, char *target "message own_private", SERVER_REC, char *msg, char *target, char *orig_target "message join", SERVER_REC, char *channel, char *nick, char *address From dab3246db91a6f17a7da192c10f9b369fa057ef5 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 12 Jul 2016 16:35:43 +0200 Subject: [PATCH 126/140] Fix the tab completion for paths starting with ./ --- src/fe-common/core/completion.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index 46fd9db7..76dfbb79 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -345,7 +345,9 @@ GList *filename_complete(const char *path, const char *default_path) (dp->d_name[1] == '.' && dp->d_name[2] == '\0')) continue; /* skip . and .. */ - if (basename[0] != '.') + /* Skip the dotfiles unless the user explicitly asked us + * to do so. Basename might be './', beware of that */ + if (basename[0] != '.' || basename[1] == '\0') continue; } From bd4189907eceed6a2c3252c7099985f975fc1654 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 12 Jul 2016 17:38:05 +0200 Subject: [PATCH 127/140] Minor cosmetic fix in /unignore error message. Reported here: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=577202 --- src/fe-common/core/fe-ignore.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index a809ac91..52b11e6b 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -215,7 +215,7 @@ static void cmd_unignore(const char *data) { IGNORE_REC *rec; GSList *tmp; - char *mask; + char *mask, *mask_orig; void *free_arg; if (!cmd_get_params(data, &free_arg, 1, &mask)) @@ -224,6 +224,10 @@ static void cmd_unignore(const char *data) if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + /* Save the mask string here since it might be modified in the code + * below and we need it to print meaningful error messages. */ + mask_orig = mask; + if (is_numeric(mask, ' ')) { /* with index number */ tmp = g_slist_nth(ignores, atoi(mask)-1); @@ -248,7 +252,7 @@ static void cmd_unignore(const char *data) ignore_update_rec(rec); } else { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, - TXT_IGNORE_NOT_FOUND, mask); + TXT_IGNORE_NOT_FOUND, mask_orig); } cmd_params_free(free_arg); } From ccf1ca124b780d18caad88d3c460d066c12e3eec Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sun, 17 Jul 2016 17:28:21 +0200 Subject: [PATCH 128/140] Wrong order in the arguments in /hilight example, -mask doesn't take a parameter --- docs/help/in/hilight.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/help/in/hilight.in b/docs/help/in/hilight.in index 2f396430..0726e5e7 100644 --- a/docs/help/in/hilight.in +++ b/docs/help/in/hilight.in @@ -32,7 +32,7 @@ /HILIGHT /HILIGHT mike /HILIGHT -regexp mi+ke+ - /HILIGHT -mask bob!*@*.irssi.org -color %%G + /HILIGHT -mask -color %%G bob!*@*.irssi.org /HILIGHT -full -color %%G -actcolor %%Y redbull %9References:%9 From 9ee480377055c04ae687c08d17f2c6b191d34db0 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 30 Mar 2016 10:14:57 +0200 Subject: [PATCH 129/140] remove curses terminal and ncurses macro --- INSTALL | 10 +- NEWS | 1 + configure.ac | 81 +--- m4/curses.m4 | 298 --------------- src/fe-text/Makefile.am | 22 +- src/fe-text/term-curses.c | 415 -------------------- src/fe-text/terminfo-core.c | 23 -- src/fe-text/tparm.c | 740 ------------------------------------ src/perl/Makefile.am | 2 +- src/perl/Makefile_silent.pm | 2 +- 10 files changed, 19 insertions(+), 1575 deletions(-) delete mode 100644 m4/curses.m4 delete mode 100644 src/fe-text/term-curses.c delete mode 100644 src/fe-text/tparm.c diff --git a/INSTALL b/INSTALL index 4b20c1ba..4c6f5681 100644 --- a/INSTALL +++ b/INSTALL @@ -59,17 +59,11 @@ configure options Build without text frontend -If ncurses is installed in a non-standard path you can specify it with ---with-ncurses=/path. If anything else is in non-standard path, you can just -give the paths in CPPFLAGS and LIBS environment variable, eg.: +If anything is in non-standard path, you can just give the paths in +CPPFLAGS and LIBS environment variable, eg.: CPPFLAGS=-I/opt/openssl/include LDFLAGS=-L/opt/openssl/lib ./configure -Irssi doesn't really need curses anymore, by default it uses -terminfo/termcap directly. The functions for using terminfo/termcap -however are usually only in curses library, some systems use libtermcap -as well. If you want to use only curses calls for some reason, use ---without-terminfo. Perl problems diff --git a/NEWS b/NEWS index 5312aef5..6666400d 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,7 @@ v0.8.20-head 2016-xx-xx The Irssi team - IP addresses are no longer stored when resolve_reverse_lookup is used. - /names and $[...] now uses utf8 string operations (#40, #411). + - Removed broken support for curses. v0.8.19 2016-03-23 The Irssi team - Fixed regression when joining and parting channels on IRCnet (#435) diff --git a/configure.ac b/configure.ac index 04e2b0b3..653dfc99 100644 --- a/configure.ac +++ b/configure.ac @@ -61,15 +61,6 @@ AC_ARG_WITH(proxy, fi, want_irssiproxy=no) -AC_ARG_WITH(terminfo, -[ --without-terminfo Use curses backend instead of terminfo], - if test x$withval = xno; then - want_terminfo=no - else - want_terminfo=yes - fi, - want_terminfo=yes) - AC_ARG_WITH(modules, [ --with-modules Specify what modules to build in binary], if test x$withval != xyes -a x$withval != xno; then @@ -314,45 +305,19 @@ dnl ** dnl ** curses checks dnl ** -if test "x$want_textui" = "xyes"; then - AC_CHECK_CURSES +if test "x$want_textui" != "xno"; then - TEXTUI_LIBS="$CURSES_LIBS" - if test "x$has_curses" = "xtrue"; then - old_libs=$LIBS - LIBS="$LIBS $CURSES_LIBS" - if test $want_terminfo = no; then - AC_CHECK_FUNC(use_default_colors, AC_DEFINE(HAVE_NCURSES_USE_DEFAULT_COLORS)) - AC_CHECK_FUNC(idcok, AC_DEFINE(HAVE_CURSES_IDCOK)) - AC_CHECK_FUNC(resizeterm, AC_DEFINE(HAVE_CURSES_RESIZETERM)) - AC_CHECK_FUNC(wresize, AC_DEFINE(HAVE_CURSES_WRESIZE)) - fi - AC_CHECK_FUNC(setupterm,, [ - want_termcap=yes - ]) - LIBS=$old_libs - else - AC_CHECK_LIB(tinfo, setupterm, [ - TEXTUI_LIBS="-ltinfo" - want_terminfo=yes - ], AC_CHECK_LIB(termlib, tgetent, [ - TEXTUI_LIBS="-ltermlib" - want_termcap=yes - ], AC_CHECK_LIB(termcap, tgetent, [ - TEXTUI_LIBS="-ltermcap" - want_termcap=yes - ], [ - AC_ERROR(Terminfo/termcap not found - install libncurses-dev or ncurses-devel package) - want_textui=no - ]))) - fi + TEXTUI_NO_LIBS="$LIBS" + LIBS= + AC_SEARCH_LIBS([setupterm], [tinfo ncursesw ncurses], [want_textui=yes], [ + AC_ERROR(Terminfo not found - install libncurses-dev or ncurses-devel package) + want_textui="no, Terminfo not found" + ]) + + TEXTUI_LIBS="$LIBS" AC_SUBST(TEXTUI_LIBS) + LIBS="$TEXTUI_NO_LIBS" - if test "x$want_termcap" = "xyes"; then - AC_CHECK_FUNC(tparm,, need_tparm=yes) - else - AC_DEFINE(HAVE_TERMINFO) - fi fi dnl ** @@ -516,8 +481,6 @@ AM_CONDITIONAL(BUILD_TEXTUI, test "$want_textui" = "yes") AM_CONDITIONAL(BUILD_IRSSIBOT, test "$want_irssibot" = "yes") AM_CONDITIONAL(BUILD_IRSSIPROXY, test "$want_irssiproxy" = "yes") AM_CONDITIONAL(HAVE_PERL, test "$want_perl" != "no") -AM_CONDITIONAL(NEED_TPARM, test "$need_tparm" = "yes") -AM_CONDITIONAL(USE_CURSES, test "$want_terminfo" != "yes" -a "$want_termcap" != "yes") # move LIBS to PROG_LIBS so they're not tried to be used when linking eg. perl libraries PROG_LIBS=$LIBS @@ -614,30 +577,19 @@ if test "x$want_dane" = "xyes"; then fi fi -if test "x$want_truecolor" = "xyes" -a "x$want_termcap" != "xyes" -a "x$want_terminfo" = "xyes" ; then +if test "x$want_truecolor" = "xyes"; then AC_DEFINE([TERM_TRUECOLOR], [], [true color support in terminal]) else want_truecolor=no fi -AH_TEMPLATE(HAS_CURSES, [macros/curses checks]) -AH_TEMPLATE(HAVE_CURSES_IDCOK) -AH_TEMPLATE(HAVE_CURSES_RESIZETERM) -AH_TEMPLATE(HAVE_CURSES_WRESIZE) AH_TEMPLATE(HAVE_GMODULE) -AH_TEMPLATE(HAVE_NCURSES_USE_DEFAULT_COLORS, [our own curses checks]) AH_TEMPLATE(HAVE_SOCKS_H, [misc..]) AH_TEMPLATE(HAVE_STATIC_PERL) -AH_TEMPLATE(HAVE_TERMINFO, [terminfo/termcap]) -AH_TEMPLATE(NO_COLOR_CURSES) AH_TEMPLATE(PRIuUOFF_T, [printf()-format for uoff_t, eg. "u" or "lu" or "llu"]) -AH_TEMPLATE(SCO_FLAVOR) AH_TEMPLATE(UOFF_T_INT, [What type should be used for uoff_t]) AH_TEMPLATE(UOFF_T_LONG) AH_TEMPLATE(UOFF_T_LONG_LONG) -AH_TEMPLATE(USE_NCURSES) -AH_TEMPLATE(USE_SUNOS_CURSES) -AH_TEMPLATE(USE_SYSV_CURSES) AC_CONFIG_FILES([ Makefile @@ -691,16 +643,7 @@ fi echo -if test "x$want_textui" = "xno"; then - text=no -elif test "x$want_termcap" = "xyes"; then - text="yes, using termcap" -elif test "x$want_terminfo" = "xyes"; then - text="yes, using terminfo" -else - text="yes, using curses" -fi -echo "Building text frontend ........... : $text" +echo "Building text frontend ........... : $want_textui" echo "Building irssi bot ............... : $want_irssibot" echo "Building irssi proxy ............. : $want_irssiproxy" if test "x$have_gmodule" = "xyes"; then diff --git a/m4/curses.m4 b/m4/curses.m4 deleted file mode 100644 index 41c0e6c8..00000000 --- a/m4/curses.m4 +++ /dev/null @@ -1,298 +0,0 @@ -dnl Curses detection: Munged from Midnight Commander's configure.in -dnl -dnl What it does: -dnl ============= -dnl -dnl - Determine which version of curses is installed on your system -dnl and set the -I/-L/-l compiler entries and add a few preprocessor -dnl symbols -dnl - Do an AC_SUBST on the CURSES_INCLUDEDIR and CURSES_LIBS so that -dnl @CURSES_INCLUDEDIR@ and @CURSES_LIBS@ will be available in -dnl Makefile.in's -dnl - Modify the following configure variables (these are the only -dnl curses.m4 variables you can access from within configure.in) -dnl CURSES_INCLUDEDIR - contains -I's and possibly -DRENAMED_CURSES if -dnl an ncurses.h that's been renamed to curses.h -dnl is found. -dnl CURSES_LIBS - sets -L and -l's appropriately -dnl CFLAGS - if --with-sco, add -D_SVID3 -dnl has_curses - exports result of tests to rest of configure -dnl -dnl Usage: -dnl ====== -dnl 1) Add lines indicated below to acconfig.h -dnl 2) call AC_CHECK_CURSES after AC_PROG_CC in your configure.in -dnl 3) Instead of #include you should use the following to -dnl properly locate ncurses or curses header file -dnl -dnl #if defined(USE_NCURSES) && !defined(RENAMED_NCURSES) -dnl #include -dnl #else -dnl #include -dnl #endif -dnl -dnl 4) Make sure to add @CURSES_INCLUDEDIR@ to your preprocessor flags -dnl 5) Make sure to add @CURSES_LIBS@ to your linker flags or LIBS -dnl -dnl Notes with automake: -dnl - call AM_CONDITIONAL(HAS_CURSES, test "$has_curses" = true) from -dnl configure.in -dnl - your Makefile.am can look something like this -dnl ----------------------------------------------- -dnl INCLUDES= blah blah blah $(CURSES_INCLUDEDIR) -dnl if HAS_CURSES -dnl CURSES_TARGETS=name_of_curses_prog -dnl endif -dnl bin_PROGRAMS = other_programs $(CURSES_TARGETS) -dnl other_programs_SOURCES = blah blah blah -dnl name_of_curses_prog_SOURCES = blah blah blah -dnl other_programs_LDADD = blah -dnl name_of_curses_prog_LDADD = blah $(CURSES_LIBS) -dnl ----------------------------------------------- -dnl -dnl -dnl The following lines should be added to acconfig.h: -dnl ================================================== -dnl -dnl /*=== Curses version detection defines ===*/ -dnl /* Found some version of curses that we're going to use */ -dnl #undef HAS_CURSES -dnl -dnl /* Use SunOS SysV curses? */ -dnl #undef USE_SUNOS_CURSES -dnl -dnl /* Use old BSD curses - not used right now */ -dnl #undef USE_BSD_CURSES -dnl -dnl /* Use SystemV curses? */ -dnl #undef USE_SYSV_CURSES -dnl -dnl /* Use Ncurses? */ -dnl #undef USE_NCURSES -dnl -dnl /* If you Curses does not have color define this one */ -dnl #undef NO_COLOR_CURSES -dnl -dnl /* Define if you want to turn on SCO-specific code */ -dnl #undef SCO_FLAVOR -dnl -dnl /* Set to reflect version of ncurses * -dnl * 0 = version 1.* -dnl * 1 = version 1.9.9g -dnl * 2 = version 4.0/4.1 */ -dnl #undef NCURSES_970530 -dnl -dnl /*=== End new stuff for acconfig.h ===*/ -dnl - - -AC_DEFUN([AC_CHECK_CURSES],[ - search_ncurses=true - screen_manager="" - has_curses=false - - CFLAGS=${CFLAGS--O} - - AC_SUBST(CURSES_LIBS) - AC_SUBST(CURSES_INCLUDEDIR) - - AC_ARG_WITH(sco, - [ --with-sco Use this to turn on SCO-specific code],[ - if test x$withval = xyes; then - AC_DEFINE(SCO_FLAVOR) - CFLAGS="$CFLAGS -D_SVID3" - fi - ]) - - AC_ARG_WITH(sunos-curses, - [ --with-sunos-curses Used to force SunOS 4.x curses],[ - if test x$withval = xyes; then - AC_USE_SUNOS_CURSES - fi - ]) - - AC_ARG_WITH(osf1-curses, - [ --with-osf1-curses Used to force OSF/1 curses],[ - if test x$withval = xyes; then - AC_USE_OSF1_CURSES - fi - ]) - - AC_ARG_WITH(vcurses, - [[ --with-vcurses[=incdir] Used to force SysV curses]], - if test x$withval != xyes; then - CURSES_INCLUDEDIR="-I$withval" - fi - AC_USE_SYSV_CURSES - ) - - AC_ARG_WITH(ncurses, - [[ --with-ncurses[=dir] Compile with ncurses/locate base dir]], - if test x$withval = xno ; then - search_ncurses=false - elif test x$withval != xyes ; then - AC_NCURSES($withval/include, ncurses.h, -L$withval/lib -lncurses, -I$withval/include, [ncurses on $withval/include]) - fi - ) - - if $search_ncurses - then - AC_SEARCH_NCURSES() - fi -]) - - -AC_DEFUN([AC_USE_SUNOS_CURSES], [ - search_ncurses=false - screen_manager="SunOS 4.x /usr/5include curses" - AC_MSG_RESULT(Using SunOS 4.x /usr/5include curses) - AC_DEFINE(USE_SUNOS_CURSES) - AC_DEFINE(HAS_CURSES) - has_curses=true - AC_DEFINE(NO_COLOR_CURSES) - AC_DEFINE(USE_SYSV_CURSES) - CURSES_INCLUDEDIR="-I/usr/5include" - CURSES_LIBS="/usr/5lib/libcurses.a /usr/5lib/libtermcap.a" - AC_MSG_RESULT(Please note that some screen refreshs may fail) -]) - -AC_DEFUN([AC_USE_OSF1_CURSES], [ - AC_MSG_RESULT(Using OSF1 curses) - search_ncurses=false - screen_manager="OSF1 curses" - AC_DEFINE(HAS_CURSES) - has_curses=true - AC_DEFINE(NO_COLOR_CURSES) - AC_DEFINE(USE_SYSV_CURSES) - CURSES_LIBS="-lcurses" -]) - -AC_DEFUN([AC_USE_SYSV_CURSES], [ - AC_MSG_RESULT(Using SysV curses) - AC_DEFINE(HAS_CURSES) - has_curses=true - AC_DEFINE(USE_SYSV_CURSES) - search_ncurses=false - screen_manager="SysV/curses" - CURSES_LIBS="-lcurses" -]) - -dnl AC_ARG_WITH(bsd-curses, -dnl [--with-bsd-curses Used to compile with bsd curses, not very fancy], -dnl search_ncurses=false -dnl screen_manager="Ultrix/cursesX" -dnl if test $system = ULTRIX -dnl then -dnl THIS_CURSES=cursesX -dnl else -dnl THIS_CURSES=curses -dnl fi -dnl -dnl CURSES_LIBS="-l$THIS_CURSES -ltermcap" -dnl AC_DEFINE(HAS_CURSES) -dnl has_curses=true -dnl AC_DEFINE(USE_BSD_CURSES) -dnl AC_MSG_RESULT(Please note that some screen refreshs may fail) -dnl AC_WARN(Use of the bsdcurses extension has some) -dnl AC_WARN(display/input problems.) -dnl AC_WARN(Reconsider using xcurses) -dnl) - - -dnl -dnl Parameters: directory filename curses_LIBS curses_INCLUDEDIR nicename -dnl -AC_DEFUN([AC_NCURSES], [ - if $search_ncurses - then - if test -f $1/$2 - then - AC_MSG_RESULT(Found ncurses on $1/$2) - - CURSES_LIBS="$3" - AC_CHECK_LIB(ncurses, initscr, [ - true; - ], [ - CHECKLIBS=`echo "$3"|sed 's/-lncurses/-lcurses/g'` - AC_CHECK_LIB(curses, initscr, [ - CURSES_LIBS="$CHECKLIBS" - ],, $CHECKLIBS) - ], $CURSES_LIBS) - CURSES_INCLUDEDIR="$4" - search_ncurses=false - screen_manager="$5" - AC_DEFINE(HAS_CURSES) - has_curses=true - has_ncurses=true - AC_DEFINE(USE_NCURSES) - fi - fi -]) - -AC_DEFUN([AC_SEARCH_NCURSES], [ - AC_CHECKING("location of ncurses.h file") - - AC_NCURSES(/usr/include, ncurses.h, -lncurses,, - [ncurses in /usr/include]) - AC_NCURSES(/usr/include/ncurses, ncurses.h, -lncurses, -I/usr/include/ncurses, - [ncurses in /usr/include/ncurses]) - AC_NCURSES(/usr/local/include, ncurses.h, -L/usr/local/lib -lncurses, -I/usr/local/include, - [ncurses in /usr/local/include]) - AC_NCURSES(/usr/local/include/ncurses, ncurses.h, -L/usr/local/lib -lncurses, -I/usr/local/include/ncurses, - [ncurses in /usr/local/include/ncurses]) - AC_NCURSES(/usr/local/include/ncurses, curses.h, -L/usr/local/lib -lncurses, -I/usr/local/include/ncurses -DRENAMED_NCURSES, - [renamed ncurses in /usr/local/include/ncurses]) - AC_NCURSES(/usr/include/ncurses, curses.h, -lncurses, -I/usr/include/ncurses -DRENAMED_NCURSES, - [renamed ncurses in /usr/include/ncurses]) - - dnl - dnl We couldn't find ncurses, try SysV curses - dnl - if $search_ncurses - then - AC_EGREP_HEADER(init_color, /usr/include/curses.h, - AC_USE_SYSV_CURSES) - AC_EGREP_CPP(USE_NCURSES,[ -#include -#ifdef __NCURSES_H -#undef USE_NCURSES -USE_NCURSES -#endif -],[ - CURSES_INCLUDEDIR="$CURSES_INCLUDEDIR -DRENAMED_NCURSES" - AC_DEFINE(HAS_CURSES) - has_curses=true - has_ncurses=true - AC_DEFINE(USE_NCURSES) - search_ncurses=false - screen_manager="ncurses installed as curses" -]) - fi - - dnl - dnl Try SunOS 4.x /usr/5{lib,include} ncurses - dnl The flags USE_SUNOS_CURSES, USE_BSD_CURSES and BUGGY_CURSES - dnl should be replaced by a more fine grained selection routine - dnl - if $search_ncurses - then - if test -f /usr/5include/curses.h - then - AC_USE_SUNOS_CURSES - fi - fi - - dnl use whatever curses there happens to be - if $search_ncurses - then - if test -f /usr/include/curses.h - then - CURSES_LIBS="-lcurses" - AC_DEFINE(HAS_CURSES) - has_curses=true - search_ncurses=false - screen_manager="curses" - fi - fi -]) - diff --git a/src/fe-text/Makefile.am b/src/fe-text/Makefile.am index b9538e60..847df150 100644 --- a/src/fe-text/Makefile.am +++ b/src/fe-text/Makefile.am @@ -4,8 +4,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/core/ \ -I$(top_srcdir)/src/fe-common/core/ \ - $(GLIB_CFLAGS) \ - $(CURSES_INCLUDEDIR) + $(GLIB_CFLAGS) irssi_DEPENDENCIES = \ @COMMON_LIBS@ \ @@ -22,25 +21,11 @@ irssi_LDADD = \ @PROG_LIBS@ \ @TEXTUI_LIBS@ -tparm_sources = \ - tparm.c - terminfo_sources = \ term-terminfo.c \ terminfo-core.c -curses_sources = \ - term-curses.c - -if NEED_TPARM -use_tparm_sources = $(tparm_sources) -endif - -if USE_CURSES -use_term_sources = $(curses_sources) -else use_term_sources = $(terminfo_sources) -endif irssi_SOURCES = \ gui-entry.c \ @@ -57,7 +42,6 @@ irssi_SOURCES = \ statusbar-items.c \ term.c \ term-dummy.c \ - $(use_tparm_sources) \ $(use_term_sources) \ textbuffer.c \ textbuffer-commands.c \ @@ -85,6 +69,4 @@ noinst_HEADERS = \ module-formats.h EXTRA_DIST = \ - $(tparm_sources) \ - $(terminfo_sources) \ - $(curses_sources) + $(terminfo_sources) diff --git a/src/fe-text/term-curses.c b/src/fe-text/term-curses.c deleted file mode 100644 index 752edd7f..00000000 --- a/src/fe-text/term-curses.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - term-curses.c : irssi - - Copyright (C) 1999-2001 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "module.h" -#include "signals.h" -#include "settings.h" - -#include "term.h" -#include "mainwindows.h" - -#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES) -# include -#else -# include -#endif -#include -#include - -#ifndef COLOR_PAIRS -# define COLOR_PAIRS 64 -#endif - -#if defined (TIOCGWINSZ) && defined (HAVE_CURSES_RESIZETERM) -# define USE_RESIZE_TERM -#endif - -#ifndef _POSIX_VDISABLE -# define _POSIX_VDISABLE 0 -#endif - -struct _TERM_WINDOW { - int x, y; - int width, height; - WINDOW *win; -}; - -TERM_WINDOW *root_window; - -static int curs_x, curs_y; -static int freeze_refresh; -static struct termios old_tio; - -static int init_curses(void) -{ - char ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; - int num; - struct termios tio; - - if (!initscr()) - return FALSE; - - cbreak(); noecho(); idlok(stdscr, 1); -#ifdef HAVE_CURSES_IDCOK - /*idcok(stdscr, 1); - disabled currently, causes redrawing problems with NetBSD */ -#endif - intrflush(stdscr, FALSE); nodelay(stdscr, TRUE); - - /* Disable INTR, QUIT, VDSUSP and SUSP keys */ - if (tcgetattr(0, &old_tio) == 0) { - memcpy(&tio, &old_tio, sizeof(tio)); - tio.c_cc[VINTR] = _POSIX_VDISABLE; - tio.c_cc[VQUIT] = _POSIX_VDISABLE; -#ifdef VDSUSP - tio.c_cc[VDSUSP] = _POSIX_VDISABLE; -#endif -#ifdef VSUSP - tio.c_cc[VSUSP] = _POSIX_VDISABLE; -#endif - tcsetattr(0, TCSADRAIN, &tio); - } - - if (has_colors()) - start_color(); - else if (term_use_colors) - term_use_colors = FALSE; - -#ifdef HAVE_NCURSES_USE_DEFAULT_COLORS - /* this lets us to use the "default" background color for colors <= 7 so - background pixmaps etc. show up right */ - use_default_colors(); - - for (num = 1; num < COLOR_PAIRS; num++) - init_pair(num, ansi_tab[num & 7], num <= 7 ? -1 : ansi_tab[num >> 3]); - - init_pair(63, 0, -1); /* hm.. not THAT good idea, but probably more - people want dark grey than white on white.. */ -#else - for (num = 1; num < COLOR_PAIRS; num++) - init_pair(num, ansi_tab[num & 7], ansi_tab[num >> 3]); - init_pair(63, 0, 0); -#endif - - clear(); - return TRUE; -} - -static int term_init_int(void) -{ - int ret; - - ret = init_curses(); - if (!ret) return 0; - - curs_x = curs_y = 0; - freeze_refresh = 0; - - root_window = g_new0(TERM_WINDOW, 1); - root_window->win = stdscr; - - term_width = COLS; - term_height = LINES; - return ret; -} - -static void term_deinit_int(void) -{ - tcsetattr(0, TCSADRAIN, &old_tio); - - endwin(); - g_free_and_null(root_window); -} - -int term_init(void) -{ - if (!term_init_int()) - return FALSE; - - settings_add_int("lookandfeel", "default_color", 7); - term_common_init(); - return TRUE; -} - -void term_deinit(void) -{ - term_common_deinit(); - term_deinit_int(); -} - -/* Resize terminal - if width or height is negative, - the new size is unknown and should be figured out somehow */ -void term_resize(int width, int height) -{ -#ifdef HAVE_CURSES_RESIZETERM - if (width < 0 || height < 0) { -#endif - term_deinit_int(); - term_init_int(); -#ifdef HAVE_CURSES_RESIZETERM - } else if (term_width != width || term_height != height) { - term_width = width; - term_height = height; - resizeterm(term_height, term_width); - } -#endif -} - -void term_resize_final(int width, int height) -{ -#ifdef HAVE_CURSES_RESIZETERM - if (width < 0 || height < 0) - mainwindows_recreate(); -#else - mainwindows_recreate(); -#endif -} - -/* Returns TRUE if terminal has colors */ -int term_has_colors(void) -{ - return has_colors(); -} - -/* Force the colors on any way you can */ -void term_force_colors(int set) -{ - /* don't do anything with curses */ -} - -/* Clear screen */ -void term_clear(void) -{ - term_set_color(root_window, 0); - clear(); -} - -/* Beep */ -void term_beep(void) -{ - beep(); -} - -/* Create a new window in terminal */ -TERM_WINDOW *term_window_create(int x, int y, int width, int height) -{ - TERM_WINDOW *window; - - window = g_new0(TERM_WINDOW, 1); - window->x = x; window->y = y; - window->width = width; window->height = height; - window->win = newwin(height, width, y, x); - if (window->win == NULL) - g_error("newwin() failed: %d,%d %d,%d", x, y, width, height); - idlok(window->win, 1); - - return window; -} - -/* Destroy a terminal window */ -void term_window_destroy(TERM_WINDOW *window) -{ - delwin(window->win); - g_free(window); -} - -/* Move/resize a window */ -void term_window_move(TERM_WINDOW *window, int x, int y, - int width, int height) -{ - /* some checks to make sure the window is visible in screen, - otherwise curses could get nasty and not show our window anymore. */ - if (width < 1) width = 1; - if (height < 1) height = 1; - if (x+width > term_width) x = term_width-width; - if (y+height > term_height) y = term_height-height; - -#ifdef HAVE_CURSES_WRESIZE - if (window->width != width || window->height != height) - wresize(window->win, height, width); - if (window->x != x || window->y != y) - mvwin(window->win, y, x); -#else - if (window->width != width || window->height != height || - window->x != x || window->y != y) { - delwin(window->win); - window->win = newwin(height, width, y, x); - idlok(window->win, 1); - } -#endif - window->x = x; window->y = y; - window->width = width; window->height = height; -} - -/* Clear window */ -void term_window_clear(TERM_WINDOW *window) -{ - werase(window->win); -} - -/* Scroll window up/down */ -void term_window_scroll(TERM_WINDOW *window, int count) -{ - scrollok(window->win, TRUE); - wscrl(window->win, count); - scrollok(window->win, FALSE); -} - -static int get_attr(int color) -{ - int attr; - - if ((color & FG_MASK) >> 4) - color = (color & ~FG_MASK) | term_color256map[color & FG_MASK]; - if ((color & BG_MASK) >> (BG_SHIFT + 4)) - color = (color & ~BG_MASK) | (term_color256map[(color & BG_MASK) >> BG_SHIFT] << BG_SHIFT); - if (!term_use_colors) - attr = (color & (0x7 << BG_SHIFT)) ? A_REVERSE : 0; - else if ((color & ((0xf << BG_SHIFT) | 0xf)) == 8 || (color & (FG_MASK | BG_MASK | ATTR_RESETFG)) == 0) - attr = COLOR_PAIR(63); - else if ((color & ((0x7 << BG_SHIFT) | 0x7)) == 0) - attr = A_NORMAL; - else { - if (color & ATTR_RESETFG) { - color &= ~FG_MASK; - color |= settings_get_int("default_color"); - } - attr = COLOR_PAIR((color&0x7) | ((color&(0x7<>BG_SHIFT<<3)); - } - - if ((color & 0x8) || (color & ATTR_BOLD)) attr |= A_BOLD; - if (color & ATTR_BLINK) attr |= A_BLINK; - - if (color & ATTR_UNDERLINE) attr |= A_UNDERLINE; - if (color & ATTR_REVERSE) attr |= A_REVERSE; -#ifdef A_ITALIC - if (color & ATTR_ITALIC) attr |= A_ITALIC; -#endif - return attr; -} - -/* Change active color */ -void term_set_color(TERM_WINDOW *window, int col) -{ - wattrset(window->win, get_attr(col)); - wbkgdset(window->win, ' ' | get_attr(col)); -} - -void term_move(TERM_WINDOW *window, int x, int y) -{ - wmove(window->win, y, x); -} - -void term_addch(TERM_WINDOW *window, char chr) -{ - waddch(window->win, chr); -} - -void term_add_unichar(TERM_WINDOW *window, unichar chr) -{ -#ifdef WIDEC_CURSES - cchar_t wch; - wchar_t temp[2]; - temp[0] = chr; - temp[1] = 0; - if (setcchar(&wch, temp, A_NORMAL, 0, NULL) == OK) - wadd_wch(window->win, &wch); - else -#endif - waddch(window->win, chr); -} - -void term_addstr(TERM_WINDOW *window, const char *str) -{ - waddstr(window->win, (const char *) str); -} - -void term_clrtoeol(TERM_WINDOW *window) -{ - wclrtoeol(window->win); -} - -void term_move_cursor(int x, int y) -{ - curs_x = x; - curs_y = y; -} - -void term_refresh_freeze(void) -{ - freeze_refresh++; -} - -void term_refresh_thaw(void) -{ - if (freeze_refresh > 0) { - freeze_refresh--; - if (freeze_refresh == 0) term_refresh(NULL); - } -} - -void term_refresh(TERM_WINDOW *window) -{ - if (window != NULL) - wnoutrefresh(window->win); - - if (freeze_refresh == 0) { - move(curs_y, curs_x); - wnoutrefresh(stdscr); - doupdate(); - } -} - -void term_stop(void) -{ - term_deinit_int(); - kill(getpid(), SIGTSTP); - term_init_int(); - irssi_redraw(); -} - -void term_set_input_type(int type) -{ -} - -void term_gets(GArray *buffer, int *line_count) -{ -#ifdef WIDEC_CURSES - wint_t key; -#else - int key; -#endif - - for (;;) { -#ifdef WIDEC_CURSES - if (get_wch(&key) == ERR) -#else - if ((key = getch()) == ERR) -#endif - break; -#ifdef KEY_RESIZE - if (key == KEY_RESIZE) - continue; -#endif - - g_array_append_val(buffer, key); - if (key == '\r' || key == '\n') - (*line_count)++; - } -} diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c index 15b00081..9c9179a5 100644 --- a/src/fe-text/terminfo-core.c +++ b/src/fe-text/terminfo-core.c @@ -17,7 +17,6 @@ inline static int term_putchar(int c) char *tparm(); int tputs(); -#ifdef HAVE_TERMINFO int setupterm(); char *tigetstr(); int tigetnum(); @@ -25,15 +24,6 @@ int tigetflag(); #define term_getstr(x, buffer) tigetstr(x.ti_name) #define term_getnum(x) tigetnum(x.ti_name); #define term_getflag(x) tigetflag(x.ti_name); -#else -int tgetent(); -char *tgetstr(); -int tgetnum(); -int tgetflag(); -#define term_getstr(x, buffer) tgetstr(x.tc_name, &buffer) -#define term_getnum(x) tgetnum(x.tc_name) -#define term_getflag(x) tgetflag(x.tc_name) -#endif #define CAP_TYPE_FLAG 0 #define CAP_TYPE_INT 1 @@ -415,9 +405,6 @@ static void term_fill_capabilities(TERM_REC *term) char *sval; void *ptr; -#ifndef HAVE_TERMINFO - char *tptr = term->buffer2; -#endif for (i = 0; i < sizeof(tcaps)/sizeof(tcaps[0]); i++) { ptr = G_STRUCT_MEMBER_P(term, tcaps[i].offset); @@ -583,9 +570,7 @@ void terminfo_stop(TERM_REC *term) static int term_setup(TERM_REC *term) { GString *str; -#ifdef HAVE_TERMINFO int err; -#endif char *term_env; term_env = getenv("TERM"); @@ -594,18 +579,10 @@ static int term_setup(TERM_REC *term) return 0; } -#ifdef HAVE_TERMINFO if (setupterm(term_env, 1, &err) != 0) { fprintf(stderr, "setupterm() failed for TERM=%s: %d\n", term_env, err); return 0; } -#else - if (tgetent(term->buffer1, term_env) < 1) - { - fprintf(stderr, "Termcap not found for TERM=%s\n", term_env); - return 0; - } -#endif term_fill_capabilities(term); diff --git a/src/fe-text/tparm.c b/src/fe-text/tparm.c deleted file mode 100644 index 97c790da..00000000 --- a/src/fe-text/tparm.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * tparm.c - * - * By Ross Ridge - * Public Domain - * 92/02/01 07:30:36 - * - */ -#include -#include -#include -#include - -#ifndef MAX_PUSHED -#define MAX_PUSHED 32 -#endif - -#define ARG 1 -#define NUM 2 - -#define INTEGER 1 -#define STRING 2 - -#define MAX_LINE 640 - -typedef void* anyptr; - -typedef struct stack_str { - int type; - int argnum; - int value; -} stack; - -static stack S[MAX_PUSHED]; -static stack vars['z'-'a'+1]; -static int pos = 0; - -static struct arg_str { - int type; - int integer; - char *string; -} arg_list[10]; - -static int argcnt; - -static va_list tparm_args; - -static int pusharg(int arg) -{ - if (pos == MAX_PUSHED) - return 1; - S[pos].type = ARG; - S[pos++].argnum = arg; - return 0; -} - -static int pushnum(int num) -{ - if (pos == MAX_PUSHED) - return 1; - S[pos].type = NUM; - S[pos++].value = num; - return 0; -} - -/* VARARGS2 */ -static int getarg(int argnum, int type, anyptr p) -{ - while (argcnt < argnum) { - arg_list[argcnt].type = INTEGER; - arg_list[argcnt++].integer = (int) va_arg(tparm_args, int); - } - if (argcnt > argnum) { - if (arg_list[argnum].type != type) - return 1; - else if (type == STRING) - *(char **)p = arg_list[argnum].string; - else - *(int *)p = arg_list[argnum].integer; - } else { - arg_list[argcnt].type = type; - if (type == STRING) - *(char **)p = arg_list[argcnt++].string - = (char *) va_arg(tparm_args, char *); - else - *(int *)p = arg_list[argcnt++].integer = (int) va_arg(tparm_args, int); - } - return 0; -} - - -static int popstring(char **str) -{ - if (pos-- == 0) - return 1; - if (S[pos].type != ARG) - return 1; - return(getarg(S[pos].argnum, STRING, (anyptr) str)); -} - -static int popnum(int *num) -{ - if (pos-- == 0) - return 1; - switch (S[pos].type) { - case ARG: - return (getarg(S[pos].argnum, INTEGER, (anyptr) num)); - case NUM: - *num = S[pos].value; - return 0; - } - return 1; -} - -static int cvtchar(const char *sp, char *c) -{ - switch(*sp) { - case '\\': - switch(*++sp) { - case '\'': - case '$': - case '\\': - case '%': - *c = *sp; - return 2; - case '\0': - *c = '\\'; - return 1; - case '0': - if (sp[1] == '0' && sp[2] == '0') { - *c = '\0'; - return 4; - } - *c = '\200'; /* '\0' ???? */ - return 2; - default: - *c = *sp; - return 2; - } - default: - *c = *sp; - return 1; - } -} - -static int termcap; - -/* sigh... this has got to be the ugliest code I've ever written. - Trying to handle everything has its cost, I guess. - - It actually isn't to hard to figure out if a given % code is supposed - to be interpeted with its termcap or terminfo meaning since almost - all terminfo codes are invalid unless something has been pushed on - the stack and termcap strings will never push things on the stack - (%p isn't used by termcap). So where we have a choice we make the - decision by whether or not somthing has been pushed on the stack. - The static variable termcap keeps track of this; it starts out set - to 1 and is incremented as each argument processed by a termcap % code, - however if something is pushed on the stack it's set to 0 and the - rest of the % codes are interpeted as terminfo % codes. Another way - of putting it is that if termcap equals one we haven't decided either - way yet, if it equals zero we're looking for terminfo codes, and if - its greater than 1 we're looking for termcap codes. - - Terminfo % codes: - - %% output a '%' - %[[:][-+# ][width][.precision]][doxXs] - output pop according to the printf format - %c output pop as a char - %'c' push character constant c. - %{n} push decimal constant n. - %p[1-9] push parameter [1-9] - %g[a-z] push variable [a-z] - %P[a-z] put pop in variable [a-z] - %l push the length of pop (a string) - %+ add pop to pop and push the result - %- subtract pop from pop and push the result - %* multiply pop and pop and push the result - %& bitwise and pop and pop and push the result - %| bitwise or pop and pop and push the result - %^ bitwise xor pop and pop and push the result - %~ push the bitwise not of pop - %= compare if pop and pop are equal and push the result - %> compare if pop is less than pop and push the result - %< compare if pop is greater than pop and push the result - %A logical and pop and pop and push the result - %O logical or pop and pop and push the result - %! push the logical not of pop - %? condition %t if_true [%e if_false] %; - if condition evaulates as true then evaluate if_true, - else evaluate if_false. elseif's can be done: -%? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %; - %i add one to parameters 1 and 2. (ANSI) - - Termcap Codes: - - %% output a % - %. output parameter as a character - %d output parameter as a decimal number - %2 output parameter in printf format %02d - %3 output parameter in printf format %03d - %+x add the character x to parameter and output it as a character -(UW) %-x subtract parameter FROM the character x and output it as a char -(UW) %ax add the character x to parameter -(GNU) %a[+*-/=][cp]x - GNU arithmetic. -(UW) %sx subtract parameter FROM the character x - %>xy if parameter > character x then add character y to parameter - %B convert to BCD (parameter = (parameter/10)*16 + parameter%16) - %D Delta Data encode (parameter = parameter - 2*(parameter%16)) - %i increment the first two parameters by one - %n xor the first two parameters by 0140 -(GNU) %m xor the first two parameters by 0177 - %r swap the first two parameters -(GNU) %b backup to previous parameter -(GNU) %f skip this parameter - - Note the two definitions of %a, the GNU definition is used if the characters - after the 'a' are valid, otherwise the UW definition is used. - - (GNU) used by GNU Emacs termcap libraries - (UW) used by the University of Waterloo (MFCF) termcap libraries - -*/ - -char *tparm(const char *str, ...) { - static char OOPS[] = "OOPS"; - static char buf[MAX_LINE]; - register const char *sp; - register char *dp; - register char *fmt; - char conv_char; - char scan_for; - int scan_depth = 0, if_depth; - static int i, j; - static char *s, c; - char fmt_buf[MAX_LINE]; - char sbuf[MAX_LINE]; - - va_start(tparm_args, str); - - sp = str; - dp = buf; - scan_for = 0; - if_depth = 0; - argcnt = 0; - pos = 0; - termcap = 1; - while (*sp != '\0') { - switch(*sp) { - case '\\': - if (scan_for) { - if (*++sp != '\0') - sp++; - break; - } - *dp++ = *sp++; - if (*sp != '\0') - *dp++ = *sp++; - break; - case '%': - sp++; - if (scan_for) { - if (*sp == scan_for && if_depth == scan_depth) { - if (scan_for == ';') - if_depth--; - scan_for = 0; - } else if (*sp == '?') - if_depth++; - else if (*sp == ';') { - if (if_depth == 0) - return OOPS; - else - if_depth--; - } - sp++; - break; - } - fmt = NULL; - switch(*sp) { - case '%': - *dp++ = *sp++; - break; - case '+': - if (!termcap) { - if (popnum(&j) || popnum(&i)) - return OOPS; - i += j; - if (pushnum(i)) - return OOPS; - sp++; - break; - } - ;/* FALLTHROUGH */ - case 'C': - if (*sp == 'C') { - if (getarg(termcap - 1, INTEGER, &i)) - return OOPS; - if (i >= 96) { - i /= 96; - if (i == '$') - *dp++ = '\\'; - *dp++ = i; - } - } - fmt = "%c"; - /* FALLTHROUGH */ - case 'a': - if (!termcap) - return OOPS; - if (getarg(termcap - 1, INTEGER, (anyptr) &i)) - return OOPS; - if (*++sp == '\0') - return OOPS; - if ((sp[1] == 'p' || sp[1] == 'c') - && sp[2] != '\0' && fmt == NULL) { - /* GNU aritmitic parameter, what they - really need is terminfo. */ - int val, lc; - if (sp[1] == 'p' - && getarg(termcap - 1 + sp[2] - '@', - INTEGER, (anyptr) &val)) - return OOPS; - if (sp[1] == 'c') { - lc = cvtchar(sp + 2, &c) + 2; - /* Mask out 8th bit so \200 can be - used for \0 as per GNU doc's */ - val = c & 0177; - } else - lc = 2; - switch(sp[0]) { - case '=': - break; - case '+': - val = i + val; - break; - case '-': - val = i - val; - break; - case '*': - val = i * val; - break; - case '/': - val = i / val; - break; - default: - /* Not really GNU's %a after all... */ - lc = cvtchar(sp, &c); - val = c + i; - break; - } - arg_list[termcap - 1].integer = val; - sp += lc; - break; - } - sp += cvtchar(sp, &c); - arg_list[termcap - 1].integer = c + i; - if (fmt == NULL) - break; - sp--; - /* FALLTHROUGH */ - case '-': - if (!termcap) { - if (popnum(&j) || popnum(&i)) - return OOPS; - i -= j; - if (pushnum(i)) - return OOPS; - sp++; - break; - } - fmt = "%c"; - /* FALLTHROUGH */ - case 's': - if (termcap && (fmt == NULL || *sp == '-')) { - if (getarg(termcap - 1, INTEGER, &i)) - return OOPS; - if (*++sp == '\0') - return OOPS; - sp += cvtchar(sp, &c); - arg_list[termcap - 1].integer = c - i; - if (fmt == NULL) - break; - sp--; - } - if (!termcap) - return OOPS; - ;/* FALLTHROUGH */ - case '.': - if (termcap && fmt == NULL) - fmt = "%c"; - ;/* FALLTHROUGH */ - case 'd': - if (termcap && fmt == NULL) - fmt = "%d"; - ;/* FALLTHROUGH */ - case '2': - if (termcap && fmt == NULL) - fmt = "%02d"; - ;/* FALLTHROUGH */ - case '3': - if (termcap && fmt == NULL) - fmt = "%03d"; - ;/* FALLTHROUGH */ - case ':': case ' ': case '#': case 'u': - case 'x': case 'X': case 'o': case 'c': - case '0': case '1': case '4': case '5': - case '6': case '7': case '8': case '9': - if (fmt == NULL) { - if (termcap) - return OOPS; - if (*sp == ':') - sp++; - fmt = fmt_buf; - *fmt++ = '%'; - while(*sp != 's' && *sp != 'x' && *sp != 'X' && *sp != 'd' && *sp != 'o' && *sp != 'c' && *sp != 'u') { - if (*sp == '\0') - return OOPS; - *fmt++ = *sp++; - } - *fmt++ = *sp; - *fmt = '\0'; - fmt = fmt_buf; - } - conv_char = fmt[strlen(fmt) - 1]; - if (conv_char == 's') { - if (popstring(&s)) - return OOPS; - sprintf(sbuf, fmt, s); - } else { - if (termcap) { - if (getarg(termcap++ - 1, - INTEGER, &i)) - return OOPS; - } else - if (popnum(&i)) - return OOPS; - if (i == 0 && conv_char == 'c') - *sbuf = 0; - else - sprintf(sbuf, fmt, i); - } - sp++; - fmt = sbuf; - while(*fmt != '\0') { - if (*fmt == '$') - *dp++ = '\\'; - *dp++ = *fmt++; - } - break; - case 'r': - if (!termcap || getarg(1, INTEGER, &i)) - return OOPS; - arg_list[1].integer = arg_list[0].integer; - arg_list[0].integer = i; - sp++; - break; - case 'i': - if (getarg(1, INTEGER, &i) - || arg_list[0].type != INTEGER) - return OOPS; - arg_list[1].integer++; - arg_list[0].integer++; - sp++; - break; - case 'n': - if (!termcap || getarg(1, INTEGER, &i)) - return OOPS; - arg_list[0].integer ^= 0140; - arg_list[1].integer ^= 0140; - sp++; - break; - case '>': - if (!termcap) { - if (popnum(&j) || popnum(&i)) - return OOPS; - i = (i > j); - if (pushnum(i)) - return OOPS; - sp++; - break; - } - if (getarg(termcap-1, INTEGER, &i)) - return OOPS; - sp += cvtchar(sp, &c); - if (i > c) { - sp += cvtchar(sp, &c); - arg_list[termcap-1].integer += c; - } else - sp += cvtchar(sp, &c); - sp++; - break; - case 'B': - if (!termcap || getarg(termcap-1, INTEGER, &i)) - return OOPS; - arg_list[termcap-1].integer = 16*(i/10)+i%10; - sp++; - break; - case 'D': - if (!termcap || getarg(termcap-1, INTEGER, &i)) - return OOPS; - arg_list[termcap-1].integer = i - 2 * (i % 16); - sp++; - break; - case 'p': - if (termcap > 1) - return OOPS; - if (*++sp == '\0') - return OOPS; - if (*sp == '0') - i = 9; - else - i = *sp - '1'; - if (i < 0 || i > 9) - return OOPS; - if (pusharg(i)) - return OOPS; - termcap = 0; - sp++; - break; - case 'P': - if (termcap || *++sp == '\0') - return OOPS; - i = *sp++ - 'a'; - if (i < 0 || i > 25) - return OOPS; - if (pos-- == 0) - return OOPS; - switch(vars[i].type = S[pos].type) { - case ARG: - vars[i].argnum = S[pos].argnum; - break; - case NUM: - vars[i].value = S[pos].value; - break; - } - break; - case 'g': - if (termcap || *++sp == '\0') - return OOPS; - i = *sp++ - 'a'; - if (i < 0 || i > 25) - return OOPS; - switch(vars[i].type) { - case ARG: - if (pusharg(vars[i].argnum)) - return OOPS; - break; - case NUM: - if (pushnum(vars[i].value)) - return OOPS; - break; - } - break; - case '\'': - if (termcap > 1) - return OOPS; - if (*++sp == '\0') - return OOPS; - sp += cvtchar(sp, &c); - if (pushnum(c) || *sp++ != '\'') - return OOPS; - termcap = 0; - break; - case '{': - if (termcap > 1) - return OOPS; - i = 0; - sp++; - while(isdigit((int) (unsigned char) *sp)) - i = 10 * i + *sp++ - '0'; - if (*sp++ != '}' || pushnum(i)) - return OOPS; - termcap = 0; - break; - case 'l': - if (termcap || popstring(&s)) - return OOPS; - i = strlen(s); - if (pushnum(i)) - return OOPS; - sp++; - break; - case '*': - if (termcap || popnum(&j) || popnum(&i)) - return OOPS; - i *= j; - if (pushnum(i)) - return OOPS; - sp++; - break; - case '/': - if (termcap || popnum(&j) || popnum(&i)) - return OOPS; - i /= j; - if (pushnum(i)) - return OOPS; - sp++; - break; - case 'm': - if (termcap) { - if (getarg(1, INTEGER, &i)) - return OOPS; - arg_list[0].integer ^= 0177; - arg_list[1].integer ^= 0177; - sp++; - break; - } - if (popnum(&j) || popnum(&i)) - return OOPS; - i %= j; - if (pushnum(i)) - return OOPS; - sp++; - break; - case '&': - if (popnum(&j) || popnum(&i)) - return OOPS; - i &= j; - if (pushnum(i)) - return OOPS; - sp++; - break; - case '|': - if (popnum(&j) || popnum(&i)) - return OOPS; - i |= j; - if (pushnum(i)) - return OOPS; - sp++; - break; - case '^': - if (popnum(&j) || popnum(&i)) - return OOPS; - i ^= j; - if (pushnum(i)) - return OOPS; - sp++; - break; - case '=': - if (popnum(&j) || popnum(&i)) - return OOPS; - i = (i == j); - if (pushnum(i)) - return OOPS; - sp++; - break; - case '<': - if (popnum(&j) || popnum(&i)) - return OOPS; - i = (i < j); - if (pushnum(i)) - return OOPS; - sp++; - break; - case 'A': - if (popnum(&j) || popnum(&i)) - return OOPS; - i = (i && j); - if (pushnum(i)) - return OOPS; - sp++; - break; - case 'O': - if (popnum(&j) || popnum(&i)) - return OOPS; - i = (i || j); - if (pushnum(i)) - return OOPS; - sp++; - break; - case '!': - if (popnum(&i)) - return OOPS; - i = !i; - if (pushnum(i)) - return OOPS; - sp++; - break; - case '~': - if (popnum(&i)) - return OOPS; - i = ~i; - if (pushnum(i)) - return OOPS; - sp++; - break; - case '?': - if (termcap > 1) - return OOPS; - termcap = 0; - if_depth++; - sp++; - break; - case 't': - if (popnum(&i) || if_depth == 0) - return OOPS; - if (!i) { - scan_for = 'e'; - scan_depth = if_depth; - } - sp++; - break; - case 'e': - if (if_depth == 0) - return OOPS; - scan_for = ';'; - scan_depth = if_depth; - sp++; - break; - case ';': - if (if_depth-- == 0) - return OOPS; - sp++; - break; - case 'b': - if (--termcap < 1) - return OOPS; - sp++; - break; - case 'f': - if (!termcap++) - return OOPS; - sp++; - break; - } - break; - default: - if (scan_for) - sp++; - else - *dp++ = *sp++; - break; - } - } - va_end(tparm_args); - *dp = '\0'; - return buf; -} diff --git a/src/perl/Makefile.am b/src/perl/Makefile.am index b17fd664..427c5492 100644 --- a/src/perl/Makefile.am +++ b/src/perl/Makefile.am @@ -127,7 +127,7 @@ am_v_pl__show_gen = $(am__v_pl__show_gen_$(V)) am_v_pl__hide_gen = $(am__v_pl__hide_gen_$(V)) am__v_pl__show_gen_ = $(am__v_pl__show_gen_$(AM_DEFAULT_VERBOSITY)) am__v_pl__hide_gen_ = $(am__v_pl__hide_gen_$(AM_DEFAULT_VERBOSITY)) -am__v_pl__show_gen_0 = echo " GEN " $$dir ; +am__v_pl__show_gen_0 = echo " GEN " $$dir ; am__v_pl__hide_gen_0 = > /dev/null am__v_pl__show_gen_1 = am__v_pl__hide_gen_1 = diff --git a/src/perl/Makefile_silent.pm b/src/perl/Makefile_silent.pm index 372e4046..b5d71d66 100644 --- a/src/perl/Makefile_silent.pm +++ b/src/perl/Makefile_silent.pm @@ -3,7 +3,7 @@ my $verb = $AM_DEFAULT_VERBOSITY; { package MY; sub _center { my $z = shift; - length $z == 2 ? " $z " : length $z == 4 ? " $z " : " $z " + (length $z == 2 ? " $z " : length $z == 4 ? " $z " : " $z ").' ' } sub _silent_cmd { my $z = shift; From b411f943a081b7c7fde0548f8c7ee5e93c0638a9 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Fri, 12 Aug 2016 18:24:58 +0200 Subject: [PATCH 130/140] fix use after free in expando error --- src/perl/common/Expando.xs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/perl/common/Expando.xs b/src/perl/common/Expando.xs index e8e8f751..bb5d185b 100644 --- a/src/perl/common/Expando.xs +++ b/src/perl/common/Expando.xs @@ -74,15 +74,18 @@ static char *perl_expando_event(PerlExpando *rec, SERVER_REC *server, ret = NULL; if (SvTRUE(ERRSV)) { + PERL_SCRIPT_REC *script = rec->script; + (void) POPs; /* call putback before emitting script error signal as that * could manipulate the perl stack. */ PUTBACK; /* make sure we don't get back here */ - if (rec->script != NULL) - script_unregister_expandos(rec->script); + if (script != NULL) + script_unregister_expandos(script); + /* rec has been freed now */ - signal_emit("script error", 2, rec->script, SvPV_nolen(ERRSV)); + signal_emit("script error", 2, script, SvPV_nolen(ERRSV)); } else if (retcount > 0) { ret = g_strdup(POPp); *free_ret = TRUE; From de11e0f4f2196d5bbb692ffe6fd0dd9afaa69e46 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Fri, 12 Aug 2016 19:33:56 +0200 Subject: [PATCH 131/140] remove broken dummy mode --- docs/irssi.1 | 3 -- src/fe-text/Makefile.am | 1 - src/fe-text/irssi.c | 85 +++++++++++++------------------ src/fe-text/term-dummy.c | 106 --------------------------------------- 4 files changed, 35 insertions(+), 160 deletions(-) delete mode 100644 src/fe-text/term-dummy.c diff --git a/docs/irssi.1 b/docs/irssi.1 index f38b639e..e1fab0d8 100644 --- a/docs/irssi.1 +++ b/docs/irssi.1 @@ -51,9 +51,6 @@ use .I HOSTNAME for your irc session .TP -.BI "\-d, \-\-dummy" -use dummy terminal mode -.TP .BI "\-v, \-\-version" display the version of Irssi .TP diff --git a/src/fe-text/Makefile.am b/src/fe-text/Makefile.am index 847df150..bdd3df22 100644 --- a/src/fe-text/Makefile.am +++ b/src/fe-text/Makefile.am @@ -41,7 +41,6 @@ irssi_SOURCES = \ statusbar-config.c \ statusbar-items.c \ term.c \ - term-dummy.c \ $(use_term_sources) \ textbuffer.c \ textbuffer-commands.c \ diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index cad271c9..ad79e0c4 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -74,10 +74,7 @@ void mainwindow_activity_deinit(void); void mainwindows_layout_init(void); void mainwindows_layout_deinit(void); -void term_dummy_init(void); -void term_dummy_deinit(void); - -static int dirty, full_redraw, dummy; +static int dirty, full_redraw; static GMainLoop *main_loop; int quitting; @@ -122,7 +119,7 @@ void irssi_set_dirty(void) static void dirty_check(void) { - if (!dirty || dummy) + if (!dirty) return; term_resize_dirty(); @@ -171,27 +168,22 @@ static void textui_finish_init(void) { quitting = FALSE; - if (dummy) - term_dummy_init(); - else { - term_refresh_freeze(); - textbuffer_init(); - textbuffer_view_init(); - textbuffer_commands_init(); - gui_expandos_init(); - gui_printtext_init(); - gui_readline_init(); - lastlog_init(); - mainwindows_init(); - mainwindow_activity_init(); - mainwindows_layout_init(); - gui_windows_init(); - statusbar_init(); - term_refresh_thaw(); + term_refresh_freeze(); + textbuffer_init(); + textbuffer_view_init(); + textbuffer_commands_init(); + gui_expandos_init(); + gui_printtext_init(); + gui_readline_init(); + lastlog_init(); + mainwindows_init(); + mainwindow_activity_init(); + mainwindows_layout_init(); + gui_windows_init(); + statusbar_init(); + term_refresh_thaw(); - /* don't check settings with dummy mode */ - settings_check(); - } + settings_check(); module_register("core", "fe-text"); @@ -233,25 +225,21 @@ static void textui_deinit(void) dirty_check(); /* one last time to print any quit messages */ signal_remove("gui exit", (SIGNAL_FUNC) sig_exit); - if (dummy) - term_dummy_deinit(); - else { - lastlog_deinit(); - statusbar_deinit(); - gui_printtext_deinit(); - gui_readline_deinit(); - gui_windows_deinit(); - mainwindows_layout_deinit(); - mainwindow_activity_deinit(); - mainwindows_deinit(); - gui_expandos_deinit(); - textbuffer_commands_deinit(); - textbuffer_view_deinit(); - textbuffer_deinit(); + lastlog_deinit(); + statusbar_deinit(); + gui_printtext_deinit(); + gui_readline_deinit(); + gui_windows_deinit(); + mainwindows_layout_deinit(); + mainwindow_activity_deinit(); + mainwindows_deinit(); + gui_expandos_deinit(); + textbuffer_commands_deinit(); + textbuffer_view_deinit(); + textbuffer_deinit(); - term_refresh_thaw(); - term_deinit(); - } + term_refresh_thaw(); + term_deinit(); theme_unregister(); @@ -276,7 +264,6 @@ int main(int argc, char **argv) { static int version = 0; static GOptionEntry options[] = { - { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, "Use the dummy terminal mode", NULL }, { "version", 'v', 0, G_OPTION_ARG_NONE, &version, "Display irssi version", NULL }, { NULL } }; @@ -295,7 +282,6 @@ int main(int argc, char **argv) srand(time(NULL)); - dummy = FALSE; quitting = FALSE; core_preinit(argv[0]); @@ -319,9 +305,8 @@ int main(int argc, char **argv) loglev = g_log_set_always_fatal(G_LOG_FATAL_MASK | G_LOG_LEVEL_CRITICAL); textui_init(); - if (!dummy && !term_init()) { - fprintf(stderr, "Can't initialize screen handling, quitting.\n"); - fprintf(stderr, "You can still use the dummy mode with -d parameter\n"); + if (!term_init()) { + fprintf(stderr, "Can't initialize screen handling.\n"); return 1; } @@ -332,9 +317,9 @@ int main(int argc, char **argv) /* Does the same as g_main_run(main_loop), except we can call our dirty-checker after each iteration */ while (!quitting) { - if (!dummy) term_refresh_freeze(); + term_refresh_freeze(); g_main_iteration(TRUE); - if (!dummy) term_refresh_thaw(); + term_refresh_thaw(); if (reload_config) { /* SIGHUP received, do /RELOAD */ diff --git a/src/fe-text/term-dummy.c b/src/fe-text/term-dummy.c deleted file mode 100644 index 6a56af88..00000000 --- a/src/fe-text/term-dummy.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - term-dummy.c : irssi - - Copyright (C) 2001 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "module.h" -#include "signals.h" - -#include "fe-windows.h" - -static int newline; - -static GIOChannel *stdin_channel; -static int readtag; -static GString *input; - -static void sig_gui_printtext(WINDOW_REC *window, void *fgcolor, - void *bgcolor, void *pflags, - char *str, void *level) -{ - if (newline) { - newline = FALSE; - printf("\r"); - } - - printf("%s", str); -} - -static void sig_gui_printtext_finished(WINDOW_REC *window) -{ - printf("\n"); - newline = TRUE; -} - -static void sig_window_created(WINDOW_REC *window) -{ - window->width = 80; - window->height = 25; -} - -static void readline(void) -{ - unsigned char buffer[128]; - char *p; - int ret, i; - - ret = read(0, buffer, sizeof(buffer)); - if (ret == 0 || (ret == -1 && errno != EINTR)) { - /* lost terminal */ - signal_emit("command quit", 1, "Lost terminal"); - return; - } - - for (i = 0; i < ret; i++) - g_string_append_c(input, buffer[i]); - - p = strchr(input->str, '\n'); - if (p != NULL) { - *p = '\0'; - signal_emit("send command", 3, input->str, - active_win->active_server, active_win->active); - *p = '\n'; - g_string_erase(input, 0, (int) (p-input->str)+1); - } -} - -void term_dummy_init(void) -{ - newline = TRUE; - input = g_string_new(NULL); - - signal_add("gui print text", (SIGNAL_FUNC) sig_gui_printtext); - signal_add("gui print text finished", (SIGNAL_FUNC) sig_gui_printtext_finished); - signal_add("window created", (SIGNAL_FUNC) sig_window_created); - - stdin_channel = g_io_channel_unix_new(0); - readtag = g_input_add_full(stdin_channel, - G_PRIORITY_HIGH, G_INPUT_READ, - (GInputFunction) readline, NULL); - g_io_channel_unref(stdin_channel); -} - -void term_dummy_deinit(void) -{ - signal_remove("gui print text", (SIGNAL_FUNC) sig_gui_printtext); - signal_remove("gui print text finished", (SIGNAL_FUNC) sig_gui_printtext_finished); - signal_remove("window created", (SIGNAL_FUNC) sig_window_created); - - g_source_remove(readtag); - g_string_free(input, TRUE); -} From 681caf2b587b88d1fcf953386b2432ce5b9bbea4 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Mon, 22 Aug 2016 12:27:10 +0200 Subject: [PATCH 132/140] fix nick->host == NULL crash --- src/fe-common/core/fe-messages.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index bc2a30d6..487a5754 100644 --- a/src/fe-common/core/fe-messages.c +++ b/src/fe-common/core/fe-messages.c @@ -603,9 +603,6 @@ static void sig_nicklist_new(CHANNEL_REC *channel, NICK_REC *nick) char *nickhost, *p; int n; - if (nick->host == NULL) - return; - firstnick = g_hash_table_lookup(channel->nicks, nick->nick); if (firstnick->next == NULL) return; @@ -618,6 +615,9 @@ static void sig_nicklist_new(CHANNEL_REC *channel, NICK_REC *nick) return; /* nope, we have it */ } + if (nick->host == NULL) + return; + /* identical nick already exists, have to change it somehow.. */ p = strchr(nick->host, '@'); if (p == NULL) p = nick->host; else p++; From 251d8a686a2717c4b1ab9dfc3599eab75105c076 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 24 Aug 2016 22:29:52 +0200 Subject: [PATCH 133/140] Fix an OOB access in the cutbuffer implementation. --- src/fe-text/gui-entry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 82645a8e..f05decd2 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -655,7 +655,7 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size, CUTBUFFER_UPDATE_OP update_ tmp->cutbuffer = g_new(unichar, cutbuffer_new_size+1); memcpy(tmp->cutbuffer, tmpcutbuffer, tmp->cutbuffer_len * sizeof(unichar)); - memcpy(tmp->cutbuffer + tmp->cutbuffer_len * sizeof(unichar), + memcpy(tmp->cutbuffer + tmp->cutbuffer_len, entry->text + entry->pos - size, size * sizeof(unichar)); tmp->cutbuffer_len = cutbuffer_new_size; From 3429c1a0a0dd336505e068dcea2a15efbf5a3c57 Mon Sep 17 00:00:00 2001 From: dequis Date: Wed, 24 Aug 2016 19:48:35 -0300 Subject: [PATCH 134/140] Set the default STATUSMSG to @ instead of @+ if it's missing This fixes two issues: - IRCNet doesn't have STATUSMSG, but it supports +channels, and including + in the default value meant processing those incorrectly - The "bahamut hack", for old servers that support but don't advertise STATUSMSG, didn't work since ischannel_func doesn't use the default. The choice of @ intentionally leaves out support for other STATUSMSG (for example, AzzurraNet's bahamut 1.4 fork seemed to support + and % in any order, contradicting the comment in the code). I think this is a decent tradeoff, given how those servers are uncommon and relying on +# or %# is even less common than @#. Fixes #531 --- src/fe-common/irc/fe-irc-channels.c | 9 +++------ src/irc/core/irc-servers.c | 6 ++++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/fe-common/irc/fe-irc-channels.c b/src/fe-common/irc/fe-irc-channels.c index a2737fc3..0ec30003 100644 --- a/src/fe-common/irc/fe-irc-channels.c +++ b/src/fe-common/irc/fe-irc-channels.c @@ -41,7 +41,7 @@ int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target) statusmsg = g_hash_table_lookup(server->isupport, "statusmsg"); if (statusmsg == NULL) - statusmsg = "@+"; + statusmsg = "@"; return strchr(statusmsg, *target) != NULL; } @@ -61,12 +61,9 @@ const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target) statusmsg = g_hash_table_lookup(server->isupport, "statusmsg"); /* Hack: for bahamut 1.4 which sends neither STATUSMSG nor - * WALLCHOPS in 005, accept @#chan and @+#chan (but not +#chan) */ - if (statusmsg == NULL && *target != '@') - return target; - + * WALLCHOPS in 005 */ if (statusmsg == NULL) - statusmsg = "@+"; + statusmsg = "@"; /* Strip the leading statusmsg prefixes */ while (strchr(statusmsg, *target) != NULL) { diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index feb7cee8..8148997b 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -89,8 +89,10 @@ static int ischannel_func(SERVER_REC *server, const char *data) chantypes = "#&!+"; /* normal, local, secure, modeless */ statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg"); - if (statusmsg != NULL) - data += strspn(data, statusmsg); + if (statusmsg == NULL) + statusmsg = "@"; + + data += strspn(data, statusmsg); /* strchr(3) considers the trailing NUL as part of the string, make sure * we didn't advance too much. */ From 5d9af40ea761850839fc22e495e68d90663c012d Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Mon, 29 Aug 2016 23:25:26 +0200 Subject: [PATCH 135/140] Update INSTALL --- INSTALL | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/INSTALL b/INSTALL index 4c6f5681..5e6e2be0 100644 --- a/INSTALL +++ b/INSTALL @@ -85,10 +85,11 @@ things that can go wrong: - If configure complains that it doesn't find some perl stuff, you're probably missing libperl.so or libperl.a. In debian, you'll need to do apt-get install libperl-dev - - For unprivileged home directory installations, using the local::lib CPAN - module is recommended. Read its docs, bootstrap it if needed, ensure that - the environment variables are set before running the configure script, and - append "--with-perl-lib=site" to the configure parameters to use it. + - For unprivileged home directory installations, you probably do not want + to specify --with-perl-lib=(site|vendor). Instead, you can use the + default perl installation target (below the irssi prefix). If you are + using local::lib you can also choose to install there by specifying + --with-perl-lib=$PERL_LOCAL_LIB_ROOT/lib/perl5 You can verify that the perl module is loaded and working with "/LOAD" command. It should print something like: From b2424f31933309a0b3dfa6cb541c2917443a38d4 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 11 Sep 2016 16:59:21 +0200 Subject: [PATCH 136/140] Add a '-autorun' switch to /script reset This way we reload all the scripts in the autorun folder. --- src/perl/perl-core.c | 2 +- src/perl/perl-core.h | 2 ++ src/perl/perl-fe.c | 13 +++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/perl/perl-core.c b/src/perl/perl-core.c index cb690906..2c61df70 100644 --- a/src/perl/perl-core.c +++ b/src/perl/perl-core.c @@ -393,7 +393,7 @@ int perl_get_api_version(void) return IRSSI_PERL_API_VERSION; } -static void perl_scripts_autorun(void) +void perl_scripts_autorun(void) { DIR *dirp; struct dirent *dp; diff --git a/src/perl/perl-core.h b/src/perl/perl-core.h index b451cc5c..7390a6fd 100644 --- a/src/perl/perl-core.h +++ b/src/perl/perl-core.h @@ -16,6 +16,8 @@ extern GSList *perl_scripts; void perl_scripts_init(void); /* Destroy all perl scripts and deinitialize perl interpreter */ void perl_scripts_deinit(void); +/* Load all the scripts in the autorun/ folder */ +void perl_scripts_autorun(void); /* Load a perl script, path must be a full path. */ PERL_SCRIPT_REC *perl_script_load_file(const char *path); diff --git a/src/perl/perl-fe.c b/src/perl/perl-fe.c index 04305b63..396c80b7 100644 --- a/src/perl/perl-fe.c +++ b/src/perl/perl-fe.c @@ -119,8 +119,20 @@ static void cmd_script_unload(const char *data) static void cmd_script_reset(const char *data) { + void *free_arg; + GHashTable *optlist; + + if (!cmd_get_params(data, &free_arg, 0 | PARAM_FLAG_OPTIONS, + "script reset", &optlist)) + return; + perl_scripts_deinit(); perl_scripts_init(); + + if (g_hash_table_lookup(optlist, "autorun") != NULL) + perl_scripts_autorun(); + + cmd_params_free(free_arg); } static void cmd_script_list(void) @@ -251,6 +263,7 @@ void fe_perl_init(void) command_bind("script list", NULL, (SIGNAL_FUNC) cmd_script_list); command_bind("load", NULL, (SIGNAL_FUNC) cmd_load); command_set_options("script exec", "permanent"); + command_set_options("script reset", "autorun"); signal_add("script error", (SIGNAL_FUNC) sig_script_error); signal_add("complete command script load", (SIGNAL_FUNC) sig_complete_load); From f492ec8abfad770e2566188e7d8721d75680e28e Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 11 Sep 2016 17:05:03 +0200 Subject: [PATCH 137/140] Document the addition of the -autorun switch for /script reset. --- docs/help/in/script.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/help/in/script.in b/docs/help/in/script.in index 6e94ef7f..e90135ad 100644 --- a/docs/help/in/script.in +++ b/docs/help/in/script.in @@ -12,6 +12,8 @@ RESET: Unloads all the scripts. -permanent: In combination with EXEC, the code will be loaded into the memory. + -autorun: When passed to RESET the scripts in the autorun folder are + reloaded. If no argument is given, the list of active scripts will be displayed. From 21539019dd46ec88a3369b53cc0069b372c6d7d1 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 13 Sep 2016 17:11:05 +0200 Subject: [PATCH 138/140] Make sure to make a copy of ERRSV content. Otherwise we might end up showing an empty message. Fixes #522. --- src/perl/common/Expando.xs | 4 +++- src/perl/textui/Statusbar.xs | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/perl/common/Expando.xs b/src/perl/common/Expando.xs index bb5d185b..26800b05 100644 --- a/src/perl/common/Expando.xs +++ b/src/perl/common/Expando.xs @@ -85,7 +85,9 @@ static char *perl_expando_event(PerlExpando *rec, SERVER_REC *server, script_unregister_expandos(script); /* rec has been freed now */ - signal_emit("script error", 2, script, SvPV_nolen(ERRSV)); + char *error = g_strdup(SvPV_nolen(ERRSV)); + signal_emit("script error", 2, script, error); + g_free(error); } else if (retcount > 0) { ret = g_strdup(POPp); *free_ret = TRUE; diff --git a/src/perl/textui/Statusbar.xs b/src/perl/textui/Statusbar.xs index a449e11d..8b0e5f65 100644 --- a/src/perl/textui/Statusbar.xs +++ b/src/perl/textui/Statusbar.xs @@ -77,7 +77,10 @@ static void perl_statusbar_event(char *function, SBAR_ITEM_REC *item, /* make sure we don't get back here */ script_unregister_statusbars(script); } - signal_emit("script error", 2, script, SvPV_nolen(ERRSV)); + + char *error = g_strdup(SvPV_nolen(ERRSV)); + signal_emit("script error", 2, script, error); + g_free(error); } else { /* min_size and max_size can be changed, move them to SBAR_ITEM_REC */ hv = hvref(item_sv); From 295a4b77f07f14602eeaa371f00ddbf09910c82b Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 14 Sep 2016 13:37:29 +0200 Subject: [PATCH 139/140] Patches for heap corruption and missing bounds check By Gabriel Campana and Adrien Guinet from Quarkslab. --- src/fe-common/core/formats.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index 3e88426f..9aa7698d 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -131,6 +131,8 @@ void unformat_24bit_color(char **ptr, int off, int *fgcolor, int *bgcolor, int * unsigned char rgbx[4]; unsigned int i; for (i = 0; i < 4; ++i) { + if ((*ptr)[i + off] == '\0') + return; rgbx[i] = (*ptr)[i + off]; } rgbx[3] -= 0x20; @@ -1341,6 +1343,9 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) bgcolor = *ptr==(char)0xff ? -1 : *ptr-'0'; } } + if (*ptr == '\0') + break; + ptr++; break; case 6: From 20b5d4d9826add4f1fc6949a0b1406953fa7bacb Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 14 Sep 2016 13:34:39 +0200 Subject: [PATCH 140/140] Update NEWS for 0.8.20 --- NEWS | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 6666400d..a76771e7 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -v0.8.20-head 2016-xx-xx The Irssi team +v0.8.21-head 2016-xx-xx The Irssi team * Removed --disable-ipv6 * /connect Network now aborts with an error if no servers have been added to that network. @@ -17,14 +17,25 @@ v0.8.20-head 2016-xx-xx The Irssi team + autolog_ignore_targets and activity_hide_targets learn a new syntax tag/* and * to ignore whole networks or everything. + /hilight got a -matchcase flag to hilight case sensitively (#421). - - /squery and /servlist commands have been restored. - - Where Irssi would previously only report "System error" on connect, - it will now try harder to retrieve the system error message. - IP addresses are no longer stored when resolve_reverse_lookup is used. - /names and $[...] now uses utf8 string operations (#40, #411). - Removed broken support for curses. +v0.8.20 2016-09-16 The Irssi team + - Correct the name of an emitted sasl signal (#484) + - Correct the prototype for the 'message private' signal (#515) + - Corrections in away and hilight help text (#477, #518) + - /squery and /servlist commands have been restored. + - Where Irssi would previously only report "System error" on connect, + it will now try harder to retrieve the system error message. + - Fixed issue with +channels not working properly (#533) + - Fixed crash in optchan when item has no server (#485) + - Fixed random remote crash in the nicklist handling (#529) + - Fixed remote crash due to incorrect bounds checking on + formats, reported by Gabriel Campana and Adrien Guinet from + Quarkslab. + v0.8.19 2016-03-23 The Irssi team - Fixed regression when joining and parting channels on IRCnet (#435) - Fixed SASL EXTERNAL (#432)