From ccc64c0050478dc0567ce9bb22dc75d541f8477e Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Thu, 26 Jun 2014 10:26:59 +0200 Subject: [PATCH 0001/1650] forward alternate_nick to Irc::Server attributes add the missing alternate_nick in Irc::Server by making an additional call to the Irc::Connect filler. this is not quite ideal but might need bigger refactoring otherwise. --- src/perl/irc/Irc.xs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs index 22a87384..601ba852 100644 --- a/src/perl/irc/Irc.xs +++ b/src/perl/irc/Irc.xs @@ -11,6 +11,7 @@ static void perl_irc_connect_fill_hash(HV *hv, IRC_SERVER_CONNECT_REC *conn) static void perl_irc_server_fill_hash(HV *hv, IRC_SERVER_REC *server) { + perl_irc_connect_fill_hash(hv, server->connrec); perl_server_fill_hash(hv, (SERVER_REC *) server); hv_store(hv, "real_address", 12, new_pv(server->real_address), 0); From 7099ae0466a6003f789393f3494c28980ddb0103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Tue, 22 Jul 2014 19:55:44 +0200 Subject: [PATCH 0002/1650] Disable -nolinks for lynx-generated text FAQ This way lynx also emits URLs for references at the bottom, like elinks does. The formating is a little different though (word wrapping), and elinks adds a "Visible links" line as well. --- autogen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autogen.sh b/autogen.sh index cf4b9798..d65bdede 100755 --- a/autogen.sh +++ b/autogen.sh @@ -28,7 +28,7 @@ cat docs/help/Makefile.am.gen|sed "s/@HELPFILES@/$files/g"|sed 's/?/\\?/g'|tr '! # .html -> .txt with lynx or elinks echo "Documentation: html -> txt..." if type lynx >/dev/null 2>&1 ; then - lynx -dump -nolist docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt + lynx -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt elif type elinks >/dev/null 2>&1 ; then elinks -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt else From 103b0e22eb7a463ee22398132449a05de96cada3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Tue, 22 Jul 2014 19:58:51 +0200 Subject: [PATCH 0003/1650] Force default locale when calling lynx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Else it ends up saying "Références" or other translation for the word. Might want to do the same for elinks... --- autogen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autogen.sh b/autogen.sh index d65bdede..b0bd2159 100755 --- a/autogen.sh +++ b/autogen.sh @@ -28,7 +28,7 @@ cat docs/help/Makefile.am.gen|sed "s/@HELPFILES@/$files/g"|sed 's/?/\\?/g'|tr '! # .html -> .txt with lynx or elinks echo "Documentation: html -> txt..." if type lynx >/dev/null 2>&1 ; then - lynx -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt + LC_ALL=C lynx -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt elif type elinks >/dev/null 2>&1 ; then elinks -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt else From 9af3df4e9d1ecfc070fe79d0cd20e035986b33b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Tue, 22 Jul 2014 21:59:31 +0200 Subject: [PATCH 0004/1650] Simplify network libraries detection with AC_SEARCH_LIBS AC_SEARCH_LIBS first tries to link without any lib, then tries each library, and sets $LIBS correctly in any case. cf. https://www.flameeyes.eu/autotools-mythbuster/autoconf/finding.html --- configure.ac | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 2a7bee0d..360af621 100644 --- a/configure.ac +++ b/configure.ac @@ -197,17 +197,9 @@ case "$host_os" in esac -AC_CHECK_FUNC(socket, [], [ - AC_CHECK_LIB(socket, socket, [ - LIBS="$LIBS -lsocket" - ]) -]) +AC_SEARCH_LIBS([socket], [socket]) -AC_CHECK_FUNC(inet_addr, [], [ - AC_CHECK_LIB(nsl, inet_addr, [ - LIBS="$LIBS -lnsl" - ]) -]) +AC_SEARCH_LIBS([inet_addr], [nsl]) dnl * gcc specific options if test "x$ac_cv_prog_gcc" = "xyes"; then From 1f9ad64ee559b05463c09796ef20b4dbe0daa37d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Tue, 22 Jul 2014 22:36:49 +0200 Subject: [PATCH 0005/1650] Simplify socklen_t type detection The previous version of AC_CHECK_TYPE() which didn't accept passing headers is obsolete anyway. The new one can be told which headers to include. Also test for sys/socket.h just for sanity. cf. https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Obsolete-Macros.html https://www.gnu.org/software/autoconf/manual/autoconf-2.64/html_node/Generic-Types.html https://svn.opendnssec.org/home/jerry/memory-usage/ldns-1.6.10/acx_nlnetlabs.m4 --- configure.ac | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 360af621..f587b93c 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PATH_PROG(perlpath, perl) AC_CHECK_HEADERS(unistd.h dirent.h sys/ioctl.h sys/resource.h) # check posix headers.. -AC_CHECK_HEADERS(sys/time.h sys/utsname.h regex.h) +AC_CHECK_HEADERS(sys/socket.h sys/time.h sys/utsname.h regex.h) AC_SYS_LARGEFILE @@ -206,21 +206,13 @@ if test "x$ac_cv_prog_gcc" = "xyes"; then CFLAGS="$CFLAGS -Wall" fi -dnl * socklen_t - AC_CHECK_TYPE() would be _really_ useful if it only would -dnl * accept header files where to find the typedef.. -AC_MSG_CHECKING([for socklen_t]) -AC_CACHE_VAL(irssi_cv_type_socklen_t, -[AC_TRY_COMPILE([ -#include -#include ], -[socklen_t t = 0; return((int)t); ], -irssi_cv_type_socklen_t=yes, -irssi_cv_type_socklen_t=no, -)]) -if test $irssi_cv_type_socklen_t = no; then -AC_DEFINE(socklen_t, int, Define to 'int' if doesn't define.) -fi -AC_MSG_RESULT($irssi_cv_type_socklen_t) +AC_CHECK_TYPE(socklen_t, , + [AC_DEFINE([socklen_t], [int], [Define to 'int' if doesn't define.])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +]) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) From c855fef06405e720cb1ceea98665af74136b61ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Tue, 22 Jul 2014 23:14:12 +0200 Subject: [PATCH 0006/1650] Drop AC_ISC_POSIX which is obsolete It's actually a NOOP in latest autoconf. cf. https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Obsolete-Macros.html#index-AC_005fISC_005fPOSIX-2084 --- configure.ac | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.ac b/configure.ac index f587b93c..047ffbbe 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,6 @@ AM_INIT_AUTOMAKE([1.9 no-define foreign]) AM_MAINTAINER_MODE -AC_ISC_POSIX AC_PROG_CC AC_PROG_CPP AM_PROG_LIBTOOL From 9d4ea891b91b6cf514a3c70dc68a22feafb17d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Tue, 22 Jul 2014 01:38:13 +0200 Subject: [PATCH 0007/1650] Also try links for docs generation Haiku has links (links2) but not elinks. Links doesn't seem to generate references however, but it's the 2nd fallback so it's better than nothing. --- autogen.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autogen.sh b/autogen.sh index b0bd2159..466a5a05 100755 --- a/autogen.sh +++ b/autogen.sh @@ -31,6 +31,8 @@ if type lynx >/dev/null 2>&1 ; then LC_ALL=C lynx -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt elif type elinks >/dev/null 2>&1 ; then elinks -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt +elif type links >/dev/null 2>&1 ; then + links -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt else echo "**Error**: No lynx or elinks present" exit 1 From 09f23d06b5262c53b65fa04d4f83cfd170d919c5 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Mon, 28 Jul 2014 13:58:13 +0200 Subject: [PATCH 0008/1650] Modify escape of ^ key so it can be used as well as Ctrl+^ Fixes FS#721 This makes Ctrl+^ and ^ bindable again as different keys. We do this by escaping single `^` as `^-`, which is not a valid control character (unlike `^^`) The original approach suggested in FS#721 is insufficient, it will break bindings such as `meta-^` because Irssi is convinced that `^` introduces a Control-key ("key combo") so it is waiting for what may follow. --- src/fe-common/core/keyboard.c | 16 +++++++++++----- src/fe-text/gui-readline.c | 4 ++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/fe-common/core/keyboard.c b/src/fe-common/core/keyboard.c index 00454401..bec1502e 100644 --- a/src/fe-common/core/keyboard.c +++ b/src/fe-common/core/keyboard.c @@ -292,12 +292,18 @@ static int expand_key(const char *key, GSList **out) } last_hyphen = !last_hyphen; } else if (*key == '^') { - /* ctrl-code */ - if (key[1] != '\0') - key++; - expand_out_char(*out, '^'); - expand_out_char(*out, *key); + + /* ctrl-code */ + if (key[1] != '\0' && key[1] != '-') { + key++; + expand_out_char(*out, *key); + } + else { + /* escaped syntax for ^, see gui-readline.c */ + expand_out_char(*out, '-'); + } + expand_out_char(*out, '-'); last_hyphen = FALSE; /* optional */ } else if (last_hyphen && i_isalpha(*key)) { diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 476a798b..e93f2293 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -393,8 +393,8 @@ static void sig_gui_key_pressed(gpointer keyp) } if (strcmp(str, "^") == 0) { - /* change it as ^^ */ - str[1] = '^'; + /* change it as ^-, that is an invalid control char */ + str[1] = '-'; str[2] = '\0'; } From a057cfecf7687caa658ed1be240c22f81a2f27a5 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Wed, 9 Jul 2014 22:05:52 +0200 Subject: [PATCH 0009/1650] test newer perls now available on travis --- .travis.yml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 04c19d88..35226645 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,22 @@ -language: c -compiler: - - gcc - - clang +language: perl +perl: + - "5.20-shrplib" + - "5.18-shrplib" + - "system-perl" +env: + - CC=clang + - CC=gcc before_install: - sudo apt-get update -qq + - perl -V - sudo apt-get build-dep -qq irssi - sudo apt-get install -qq lynx +install: true + script: - - ./autogen.sh --with-proxy --with-bot + - ./autogen.sh --with-proxy --with-bot --with-perl=module - cat config.log - make - sudo make install From 1b3e74645af996a3ec46a72bfb098f1506515f8a Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Sat, 9 Aug 2014 12:05:28 +0100 Subject: [PATCH 0010/1650] Include commit and if the tree is dirty in builds of -head versions --- Makefile.am | 3 ++- irssi-version.sh | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 4cebd112..6ca69fc7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,7 +12,8 @@ default-theme.h: $(srcdir)/default.theme $(srcdir)/file2header.sh $(srcdir)/default.theme default_theme > default-theme.h irssi-version.h: - $(srcdir)/irssi-version.sh $(srcdir) | cmp -s - $@ || $(srcdir)/irssi-version.sh $(srcdir) >$@ + VERSION="$(VERSION)" $(srcdir)/irssi-version.sh $(srcdir) | \ + cmp -s - $@ || VERSION="$(VERSION)" $(srcdir)/irssi-version.sh $(srcdir) >$@ SUBDIRS = src docs scripts diff --git a/irssi-version.sh b/irssi-version.sh index 49abc55e..7588182d 100755 --- a/irssi-version.sh +++ b/irssi-version.sh @@ -7,3 +7,15 @@ VERSION_TIME=`echo $DATE | cut -f 2 -d ' ' | awk -F: '{printf "%d", $1$2}'` echo "#define IRSSI_VERSION_DATE $VERSION_DATE" echo "#define IRSSI_VERSION_TIME $VERSION_TIME" + +if echo "${VERSION}" | grep -q -- -head; then + # -head version, get extra details from git if we can + git_version=$(GIT_DIR=$1/.git git describe --dirty --long --always --tags) + if [ $? = 0 ]; then + new_version="$(echo "${VERSION}" | sed 's/-head//')" + # Because the git tag won't yet include the next release we modify the git + # describe output using the version defined from configure.ac. + version="${new_version}-$(echo "${git_version}" | sed 's/^.*-[0-9]\+-//')" + echo "#define PACKAGE_VERSION \"${version}\"" + fi +fi From d9deafe57ccf2fc2191f48c989859e87b7daab06 Mon Sep 17 00:00:00 2001 From: Paul Johnson Date: Sat, 23 Aug 2014 21:08:17 +0200 Subject: [PATCH 0011/1650] Speed up /reload when there are many ignores. With many ignores (a few thousand) /reload could take so long that connections were dropped. The problem is that nickmatch_rebuild() was being called for every ignore. The easy solution is to only call it once at the end. --- src/core/ignore.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/ignore.c b/src/core/ignore.c index 3c45967c..68fae11f 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -360,8 +360,6 @@ static void ignore_destroy(IGNORE_REC *rec, int send_signal) g_free_not_null(rec->servertag); g_free_not_null(rec->pattern); g_free(rec); - - nickmatch_rebuild(nickmatch); } void ignore_update_rec(IGNORE_REC *rec) @@ -380,8 +378,8 @@ void ignore_update_rec(IGNORE_REC *rec) ignore_init_rec(rec); signal_emit("ignore changed", 1, rec); - nickmatch_rebuild(nickmatch); } + nickmatch_rebuild(nickmatch); } static int unignore_timeout(void) From 98435fb4649367c182e35aea8c89ce7a4cf8d4d3 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Thu, 11 Sep 2014 18:15:06 +0200 Subject: [PATCH 0012/1650] support storing and replaying the monospace attribute in textbuffer --- src/fe-text/textbuffer-view.c | 3 +++ src/fe-text/textbuffer.c | 8 ++++++++ src/fe-text/textbuffer.h | 1 + 3 files changed, 12 insertions(+) diff --git a/src/fe-text/textbuffer-view.c b/src/fe-text/textbuffer-view.c index 3099ee3e..ad4c00b8 100644 --- a/src/fe-text/textbuffer-view.c +++ b/src/fe-text/textbuffer-view.c @@ -146,6 +146,9 @@ static void update_cmd_color(unsigned char cmd, int *color) case LINE_CMD_ITALIC: *color ^= ATTR_ITALIC; break; + case LINE_CMD_MONOSPACE: + /* ignored */ + break; case LINE_CMD_COLOR0: *color &= BGATTR; *color &= ~ATTR_FGCOLOR24; diff --git a/src/fe-text/textbuffer.c b/src/fe-text/textbuffer.c index 24ee62bc..561fdabd 100644 --- a/src/fe-text/textbuffer.c +++ b/src/fe-text/textbuffer.c @@ -326,6 +326,10 @@ void textbuffer_line_add_colors(TEXT_BUFFER_REC *buffer, LINE_REC **line, data[pos++] = 0; data[pos++] = LINE_CMD_ITALIC; } + if ((flags & GUI_PRINT_FLAG_MONOSPACE) != (buffer->last_flags & GUI_PRINT_FLAG_MONOSPACE)) { + data[pos++] = 0; + data[pos++] = LINE_CMD_MONOSPACE; + } if (flags & GUI_PRINT_FLAG_INDENT) { data[pos++] = 0; data[pos++] = LINE_CMD_INDENT; @@ -509,6 +513,10 @@ void textbuffer_line2text(LINE_REC *line, int coloring, GString *str) g_string_append_printf(str, "\004%c", FORMAT_STYLE_ITALIC); break; + case LINE_CMD_MONOSPACE: + g_string_append_printf(str, "\004%c", + FORMAT_STYLE_MONOSPACE); + break; case LINE_CMD_COLOR0: g_string_append_printf(str, "\004%c%c", '0', FORMAT_COLOR_NOCHANGE); diff --git a/src/fe-text/textbuffer.h b/src/fe-text/textbuffer.h index eacfd447..303789a3 100644 --- a/src/fe-text/textbuffer.h +++ b/src/fe-text/textbuffer.h @@ -18,6 +18,7 @@ enum { LINE_CMD_BLINK, /* enable/disable blink */ LINE_CMD_BOLD, /* enable/disable bold */ LINE_CMD_ITALIC, /* enable/disable italic */ + LINE_CMD_MONOSPACE, /* enable/disable monospace (gui only) */ LINE_COLOR_EXT, /* extended color */ LINE_COLOR_EXT_BG, /* extended bg */ #ifdef TERM_TRUECOLOR From d9ea224628af1a4394fec20610e136a3c6817f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sun, 28 Sep 2014 15:48:48 +0200 Subject: [PATCH 0013/1650] Fix use-after-free bug with cached settings values This patch fixes a couple of use-after-free bugs when caching various string related setting values. Fixes: #143 --- src/core/expandos.c | 22 ++++++++++++++-------- src/core/log.c | 20 ++++++++++++-------- src/fe-common/core/chat-completion.c | 14 +++++++++++--- src/fe-common/core/fe-log.c | 24 +++++++++++++++++------- 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/core/expandos.c b/src/core/expandos.c index bed6c5eb..1fc517af 100644 --- a/src/core/expandos.c +++ b/src/core/expandos.c @@ -57,7 +57,7 @@ static char *last_sent_msg, *last_sent_msg_body; static char *last_privmsg_from, *last_public_from; static char *sysname, *sysrelease, *sysarch; -static const char *timestamp_format; +static char *timestamp_format; static int timestamp_seconds; static time_t last_timestamp; @@ -567,7 +567,9 @@ static int sig_timer(void) static void read_settings(void) { - timestamp_format = settings_get_str("timestamp_format"); + g_free_not_null(timestamp_format); + timestamp_format = g_strdup(settings_get_str("timestamp_format")); + timestamp_seconds = strstr(timestamp_format, "%r") != NULL || strstr(timestamp_format, "%s") != NULL || @@ -708,14 +710,18 @@ void expandos_deinit(void) g_free_not_null(char_expandos[n]); g_hash_table_foreach_remove(expandos, free_expando, NULL); - g_hash_table_destroy(expandos); + g_hash_table_destroy(expandos); - g_free_not_null(last_sent_msg); g_free_not_null(last_sent_msg_body); - g_free_not_null(last_privmsg_from); g_free_not_null(last_public_from); - g_free_not_null(sysname); g_free_not_null(sysrelease); - g_free_not_null(sysarch); + g_free_not_null(last_sent_msg); + g_free_not_null(last_sent_msg_body); + g_free_not_null(last_privmsg_from); + g_free_not_null(last_public_from); + g_free_not_null(sysname); + g_free_not_null(sysrelease); + g_free_not_null(sysarch); + g_free_not_null(timestamp_format); - g_source_remove(timer_tag); + g_source_remove(timer_tag); signal_remove("message public", (SIGNAL_FUNC) sig_message_public); signal_remove("message private", (SIGNAL_FUNC) sig_message_private); signal_remove("message own_private", (SIGNAL_FUNC) sig_message_own_private); diff --git a/src/core/log.c b/src/core/log.c index 263b3526..d4d3853e 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -41,7 +41,7 @@ static const char *log_item_types[] = { NULL }; -const char *log_timestamp; +static char *log_timestamp; static int log_file_create_mode; static int log_dir_create_mode; static int rotate_tag; @@ -558,13 +558,15 @@ static void log_read_config(void) static void read_settings(void) { - log_timestamp = settings_get_str("log_timestamp"); + g_free_not_null(log_timestamp); + log_timestamp = g_strdup(settings_get_str("log_timestamp")); + log_file_create_mode = octal2dec(settings_get_int("log_create_mode")); - log_dir_create_mode = log_file_create_mode; - if (log_file_create_mode & 0400) log_dir_create_mode |= 0100; - if (log_file_create_mode & 0040) log_dir_create_mode |= 0010; - if (log_file_create_mode & 0004) log_dir_create_mode |= 0001; + log_dir_create_mode = log_file_create_mode; + if (log_file_create_mode & 0400) log_dir_create_mode |= 0100; + if (log_file_create_mode & 0040) log_dir_create_mode |= 0010; + if (log_file_create_mode & 0004) log_dir_create_mode |= 0001; } void log_init(void) @@ -595,7 +597,9 @@ void log_deinit(void) while (logs != NULL) log_close(logs->data); + g_free_not_null(log_timestamp); + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); - signal_remove("setup reread", (SIGNAL_FUNC) log_read_config); - signal_remove("irssi init finished", (SIGNAL_FUNC) log_read_config); + signal_remove("setup reread", (SIGNAL_FUNC) log_read_config); + signal_remove("irssi init finished", (SIGNAL_FUNC) log_read_config); } diff --git a/src/fe-common/core/chat-completion.c b/src/fe-common/core/chat-completion.c index aba76b9d..c37c77cd 100644 --- a/src/fe-common/core/chat-completion.c +++ b/src/fe-common/core/chat-completion.c @@ -40,7 +40,7 @@ static int keep_privates_count, keep_publics_count; static int completion_lowercase; -static const char *completion_char, *cmdchars; +static char *completion_char, *cmdchars; static GSList *global_lastmsgs; static int completion_auto, completion_strict; @@ -1126,11 +1126,16 @@ static void read_settings(void) keep_privates_count = settings_get_int("completion_keep_privates"); keep_publics_count = settings_get_int("completion_keep_publics"); completion_lowercase = settings_get_bool("completion_nicks_lowercase"); - completion_char = settings_get_str("completion_char"); - cmdchars = settings_get_str("cmdchars"); + completion_auto = settings_get_bool("completion_auto"); completion_strict = settings_get_bool("completion_strict"); + g_free_not_null(completion_char); + completion_char = g_strdup(settings_get_str("completion_char")); + + g_free_not_null(cmdchars); + cmdchars = g_strdup(settings_get_str("cmdchars")); + if (*completion_char == '\0') { /* this would break.. */ completion_auto = FALSE; @@ -1220,4 +1225,7 @@ void chat_completion_deinit(void) signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + + g_free_not_null(completion_char); + g_free_not_null(cmdchars); } diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index 5ee72d8b..9d68faf9 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -43,11 +43,11 @@ static int autolog_level; static int autoremove_tag; -static const char *autolog_path; +static char *autolog_path; static THEME_REC *log_theme; static int skip_next_printtext; -static const char *log_theme_name; +static char *log_theme_name; static int log_dir_create_mode; @@ -675,9 +675,11 @@ static void sig_theme_destroyed(THEME_REC *theme) static void read_settings(void) { int old_autolog = autolog_level; - int log_file_create_mode; + int log_file_create_mode; + + g_free_not_null(autolog_path); + autolog_path = g_strdup(settings_get_str("autolog_path")); - autolog_path = settings_get_str("autolog_path"); autolog_level = !settings_get_bool("autolog") ? 0 : settings_get_level("autolog_level"); @@ -687,9 +689,14 @@ static void read_settings(void) /* write to log files with different theme? */ if (log_theme_name != NULL) signal_remove("print format", (SIGNAL_FUNC) sig_print_format); - log_theme_name = settings_get_str("log_theme"); - if (*log_theme_name == '\0') + + g_free_not_null(log_theme_name); + log_theme_name = g_strdup(settings_get_str("log_theme")); + + if (*log_theme_name == '\0') { + g_free(log_theme_name); log_theme_name = NULL; + } else signal_add("print format", (SIGNAL_FUNC) sig_print_format); @@ -752,7 +759,7 @@ void fe_log_deinit(void) { g_source_remove(autoremove_tag); if (log_theme_name != NULL) - signal_remove("print format", (SIGNAL_FUNC) sig_print_format); + signal_remove("print format", (SIGNAL_FUNC) sig_print_format); command_unbind("log", (SIGNAL_FUNC) cmd_log); command_unbind("log open", (SIGNAL_FUNC) cmd_log_open); @@ -776,4 +783,7 @@ void fe_log_deinit(void) if (autolog_ignore_targets != NULL) g_strfreev(autolog_ignore_targets); + + g_free_not_null(autolog_path); + g_free_not_null(log_theme_name); } From 0236ee5eaabac05e21cede2ee9b68db70019f1b7 Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Tue, 26 Feb 2008 17:29:10 +0100 Subject: [PATCH 0014/1650] PROXY: implemented native proxy support This patch creates a hook into the net_connect*() methods which call a method to connect to a proxy. Previous solution to send certain strings in the normal IRC dialog was some kind of hack as most proxies require some kind of negotation. E.g. HTTP proxies sent a 'HTTP/1.0 200 Connection established' HTTP header and clients have to wait for it. Else, sent bytes of the following IRC login will be dropped silently. With old method, it is also impossible to tunnel SSL IRC connections through the proxy as proxy speaks plain text or a special protocol while e.g. 'CONNECT ... HTTP/1.0' will be encrypted with key of IRC server. There are further enhancements possible: the whole net_connect stuff should be made asynchronously. Currently, only the hostname is resolved in the background (which makes little sense of local proxies usually). --- src/core/Makefile.am | 3 + src/core/network-openssl.c | 4 +- src/core/network-proxy-priv.h | 128 ++++++++++++++++++++++++++++++++++ src/core/network-proxy.c | 30 ++++++++ src/core/network-proxy.h | 81 +++++++++++++++++++++ src/core/network.c | 15 +++- src/core/network.h | 6 +- src/core/server-connect-rec.h | 5 +- src/core/servers-reconnect.c | 7 +- src/core/servers-setup.c | 15 ++-- src/core/servers.c | 23 +++--- src/irc/core/irc-servers.c | 28 +++----- 12 files changed, 297 insertions(+), 48 deletions(-) create mode 100644 src/core/network-proxy-priv.h create mode 100644 src/core/network-proxy.c create mode 100644 src/core/network-proxy.h diff --git a/src/core/Makefile.am b/src/core/Makefile.am index fc32e17e..ce4b4bb6 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -31,6 +31,9 @@ libcore_a_SOURCES = \ net-sendbuffer.c \ network.c \ network-openssl.c \ + network-proxy.c \ + network-proxy.h \ + network-proxy-priv.h \ nicklist.c \ nickmatch-cache.c \ pidwait.c \ diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 768fd540..1ef2c99c 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -552,11 +552,11 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ return gchan; } -GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, SERVER_REC *server) +GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify) { GIOChannel *handle, *ssl_handle; - handle = net_connect_ip(ip, port, my_ip); + handle = net_connect_proxy(proxy, host, port, ip, my_ip); if (handle == NULL) return NULL; ssl_handle = irssi_ssl_get_iochannel(handle, port, server); diff --git a/src/core/network-proxy-priv.h b/src/core/network-proxy-priv.h new file mode 100644 index 00000000..0a8f2449 --- /dev/null +++ b/src/core/network-proxy-priv.h @@ -0,0 +1,128 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * 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; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef H_IRSSI_SRC_CORE_PROXY_PRIV_H +#define H_IRSSI_SRC_CORE_PROXY_PRIV_H + +#include "settings.h" +#include + +/* stolen from linux kernel */ +#define container_of(ptr, type, member) __extension__ ({ \ + const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + + +inline static void +_network_proxy_create(struct network_proxy *dst) +{ + dst->port = settings_get_int("proxy_port"); + dst->host = g_strdup(settings_get_str("proxy_address")); +} + +inline static void +_network_proxy_clone(struct network_proxy *dst, struct network_proxy const *src) +{ + dst->host = g_strdup(src->host); + dst->port = src->port; + + dst->destroy = src->destroy; + dst->connect = src->connect; + dst->clone = src->clone; +} + +inline static void +_network_proxy_destroy(struct network_proxy *proxy) +{ + g_free((void *)proxy->host); +} + + + +inline static bool +_network_proxy_send_all(GIOChannel *ch, void const *buf, ssize_t len) +{ + GError *err = NULL; + gsize written; + GIOStatus status; + + while ((status=g_io_channel_write_chars(ch, buf, len, &written, + &err))==G_IO_STATUS_AGAIN) + continue; + + if (status==G_IO_STATUS_NORMAL) + return true; + + if (err) { + g_warning("failed to send proxy request: %s", err->message); + g_error_free(err); + } + + return false; +} + +inline static bool +_network_proxy_recv_all(GIOChannel *ch, void *buf_v, size_t len) +{ + GError *err = NULL; + gchar *buf = buf_v; + + while (len>0) { + GIOStatus status; + gsize l; + + status = g_io_channel_read_chars(ch, buf, len, &l, &err); + if (status==G_IO_STATUS_AGAIN) + continue; + if (status!=G_IO_STATUS_NORMAL) + break; + + buf += l; + len -= l; + } + + if (len==0) + return true; + + if (err) { + g_warning("failed to send proxy request: %s", err->message); + g_error_free(err); + } + + return false; +} + +inline static bool +_network_proxy_flush(GIOChannel *ch) +{ + GError *err = NULL; + GIOStatus status; + + while ((status=g_io_channel_flush(ch, &err))==G_IO_STATUS_AGAIN) + continue; + + if (status==G_IO_STATUS_NORMAL) + return true; + + if (err) { + g_warning("failed to flush proxy channel: %s", err->message); + g_error_free(err); + } + + return false; +} + +#endif /* H_IRSSI_SRC_CORE_PROXY_PRIV_H */ diff --git a/src/core/network-proxy.c b/src/core/network-proxy.c new file mode 100644 index 00000000..cedf96b5 --- /dev/null +++ b/src/core/network-proxy.c @@ -0,0 +1,30 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * 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; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "module.h" + +#include "network-proxy.h" +#include + +struct network_proxy * +network_proxy_create(char const *type) +{ + if (type==NULL) + return NULL; + + g_error("unsupported proxy type '%s'", type); + return NULL; +} diff --git a/src/core/network-proxy.h b/src/core/network-proxy.h new file mode 100644 index 00000000..cdc3d057 --- /dev/null +++ b/src/core/network-proxy.h @@ -0,0 +1,81 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * 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; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef H_IRSSI_SRC_CORE_PROXY_H +#define H_IRSSI_SRC_CORE_PROXY_H + +#include +#include + +/* helper structure for the send_string*() functions of the network_proxy + * class */ +struct network_proxy_send_string_info +{ + char const *host; /* hostname of the IRC server */ + uint16_t port; /* portnumber of the IRC server */ + + /* function which is used to send string; usually irc_send_cmd_now() */ + void (*func)(void *obj, char const *); + + /* object for func */ + void *obj; +}; + +struct network_proxy { + /* destroys the network_proxy structure which must not be used anymore + * after; this memberfunction is mandatory */ + void (*destroy)(struct network_proxy *); + + /* connects through the proxy; this memberfunction is mandatory + * + * \arg hint_ip the asynchronously resolved ip of the proxy; when + * NULL, method will resolve it itself + * \arg address the hostname where proxy shall connect to + * \arg port port address where proxy shall connect to + */ + GIOChannel * (*connect)(struct network_proxy const *, IPADDR const *hint_ip, + char const *address, int port); + + /* clones the given network_proxy object; this memberfunction is + * mandatory */ + struct network_proxy * (*clone)(struct network_proxy const *); + + + /* sends a string after connection has been established but before IRC + * authentication begins; this memberfunction is optional + */ + void (*send_string)(struct network_proxy const *, + struct network_proxy_send_string_info const *); + + /* sends a string after connection IRC authentication suceeded; this + * memberfunction is optional + */ + void (*send_string_after)(struct network_proxy const *, + struct network_proxy_send_string_info const *); + + + /* hostname of proxy host */ + char const *host; + + /* portnumber of proxy */ + int port; +}; + +/* factory method to create a proxy object based upon value of 'type' */ +struct network_proxy * network_proxy_create(char const *type); + + +#endif /* H_IRSSI_SRC_CORE_PROXY_H */ diff --git a/src/core/network.c b/src/core/network.c index 3659ab36..b65c376d 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -20,6 +20,7 @@ #include "module.h" #include "network.h" +#include "network-proxy.h" #include @@ -169,7 +170,7 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) } /* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) +GIOChannel *net_connect_ip(IPADDR const *ip, int port, IPADDR *my_ip) { union sockaddr_union so; int handle, ret, opt = 1; @@ -226,6 +227,18 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) return g_io_channel_new(handle); } +/* Connect to socket */ +GIOChannel *net_connect_proxy(struct network_proxy const *proxy, + char const *host, int port, IPADDR *ip, IPADDR *my_ip) +{ + + if (proxy) + return proxy->connect(proxy, ip, host, port); + else + return net_connect_ip(ip, port, my_ip); +} + + /* Connect to named UNIX socket */ GIOChannel *net_connect_unix(const char *path) { diff --git a/src/core/network.h b/src/core/network.h index fa7e9675..af9c6983 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -39,6 +39,7 @@ struct _IPADDR { #define IPADDR_IS_V6(ip) ((ip)->family != AF_INET) +struct network_proxy; extern IPADDR ip4_any; GIOChannel *g_io_channel_new(int handle); @@ -49,10 +50,11 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ -GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, SERVER_REC *server); +GIOChannel *net_connect_ip(IPADDR const *ip, int port, IPADDR *my_ip); +GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify); int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); +GIOChannel *net_connect_proxy(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip); /* Connect to named UNIX socket */ GIOChannel *net_connect_unix(const char *path); /* Disconnect socket */ diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h index 17537508..ac99df8d 100644 --- a/src/core/server-connect-rec.h +++ b/src/core/server-connect-rec.h @@ -5,10 +5,7 @@ int chat_type; /* chat_protocol_lookup(xx) */ int refcount; -/* if we're connecting via proxy, or just NULLs */ -char *proxy; -int proxy_port; -char *proxy_string, *proxy_string_after, *proxy_password; +struct network_proxy *proxy; unsigned short family; /* 0 = don't care, AF_INET or AF_INET6 */ char *tag; /* try to keep this tag when connected to server */ diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index 0a08b461..3ee498ed 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -29,6 +29,7 @@ #include "servers-reconnect.h" #include "settings.h" +#include "network-proxy.h" GSList *reconnects; static int last_reconnect_tag; @@ -157,11 +158,7 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info) server_connect_ref(dest); dest->type = module_get_uniq_id("SERVER CONNECT", 0); dest->reconnection = src->reconnection; - dest->proxy = g_strdup(src->proxy); - dest->proxy_port = src->proxy_port; - dest->proxy_string = g_strdup(src->proxy_string); - dest->proxy_string_after = g_strdup(src->proxy_string_after); - dest->proxy_password = g_strdup(src->proxy_password); + dest->proxy = src->proxy ? src->proxy->clone(src->proxy) : NULL; dest->tag = g_strdup(src->tag); diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 0819ff1a..87470266 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -28,6 +28,7 @@ #include "chatnets.h" #include "servers.h" #include "servers-setup.h" +#include "network-proxy.h" GSList *setupservers; @@ -126,15 +127,6 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn, conn->username = g_strdup(settings_get_str("user_name")); conn->realname = g_strdup(settings_get_str("real_name")); - /* proxy settings */ - if (settings_get_bool("use_proxy")) { - conn->proxy = g_strdup(settings_get_str("proxy_address")); - conn->proxy_port = settings_get_int("proxy_port"); - conn->proxy_string = g_strdup(settings_get_str("proxy_string")); - conn->proxy_string_after = g_strdup(settings_get_str("proxy_string_after")); - conn->proxy_password = g_strdup(settings_get_str("proxy_password")); - } - /* source IP */ if (source_host_ip4 != NULL) { conn->own_ip4 = g_new(IPADDR, 1); @@ -145,6 +137,10 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn, memcpy(conn->own_ip6, source_host_ip6, sizeof(IPADDR)); } + /* proxy settings */ + if (settings_get_bool("use_proxy")) + conn->proxy = network_proxy_create(settings_get_str("proxy_type")); + signal_emit("server setup fill connect", 1, conn); } @@ -546,6 +542,7 @@ void servers_setup_init(void) settings_add_str("proxy", "proxy_string", "CONNECT %s %d"); settings_add_str("proxy", "proxy_string_after", ""); settings_add_str("proxy", "proxy_password", ""); + settings_add_str("proxy", "proxy_type", "simple"); setupservers = NULL; source_host_ip4 = source_host_ip6 = NULL; diff --git a/src/core/servers.c b/src/core/servers.c index 06f82d4d..39b54f9a 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -34,6 +34,7 @@ #include "servers-setup.h" #include "channels.h" #include "queries.h" +#include "network-proxy.h" GSList *servers, *lookup_servers; @@ -221,10 +222,18 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip, own_ip = ip == NULL ? NULL : (IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4); - port = server->connrec->proxy != NULL ? - server->connrec->proxy_port : server->connrec->port; + port = server->connrec->port; handle = server->connrec->use_ssl ? - net_connect_ip_ssl(ip, port, own_ip, server) : net_connect_ip(ip, port, own_ip); + net_connect_proxy_ssl(server->connrec->proxy, + server->connrec->address, port, + ip, own_ip, + server->connrec->ssl_cert, + server->connrec->ssl_pkey, + server->connrec->ssl_cafile, + server->connrec->ssl_capath, server->connrec->ssl_verify) : + net_connect_proxy(server->connrec->proxy, + server->connrec->address, port, + ip, own_ip); } else { handle = net_connect_unix(unix_socket); } @@ -421,7 +430,7 @@ int server_start_connect(SERVER_REC *server) server->connect_pipe[1] = g_io_channel_new(fd[1]); connect_address = server->connrec->proxy != NULL ? - server->connrec->proxy : server->connrec->address; + server->connrec->proxy->host : server->connrec->address; server->connect_pid = net_gethostbyname_nonblock(connect_address, server->connect_pipe[1], @@ -616,10 +625,8 @@ void server_connect_unref(SERVER_CONNECT_REC *conn) if (conn->connect_handle != NULL) net_disconnect(conn->connect_handle); - g_free_not_null(conn->proxy); - g_free_not_null(conn->proxy_string); - g_free_not_null(conn->proxy_string_after); - g_free_not_null(conn->proxy_password); + if (conn->proxy) + conn->proxy->destroy(conn->proxy); g_free_not_null(conn->tag); g_free_not_null(conn->address); diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 27878989..1bf67ac3 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -37,6 +37,7 @@ #include "servers-reconnect.h" #include "servers-redirect.h" #include "modes.h" +#include "network-proxy.h" #include "settings.h" #include "recode.h" @@ -195,23 +196,19 @@ static void server_init(IRC_SERVER_REC *server) IRC_SERVER_CONNECT_REC *conn; char *address, *ptr, *username, *cmd; GTimeVal now; + struct network_proxy_send_string_info const send_info = { + .host = server->connrec->address, + .port = server->connrec->port, + .func = irc_send_cmd_now_wrapper, + .obj = server + }; g_return_if_fail(server != NULL); conn = server->connrec; - if (conn->proxy != NULL && conn->proxy_password != NULL && - *conn->proxy_password != '\0') { - cmd = g_strdup_printf("PASS %s", conn->proxy_password); - irc_send_cmd_now(server, cmd); - g_free(cmd); - } - - if (conn->proxy != NULL && conn->proxy_string != NULL) { - cmd = g_strdup_printf(conn->proxy_string, conn->address, conn->port); - irc_send_cmd_now(server, cmd); - g_free(cmd); - } + if (conn->proxy && conn->proxy->send_string) + conn->proxy->send_string(conn->proxy, &send_info); if (conn->password != NULL && *conn->password != '\0') { /* send password */ @@ -245,11 +242,8 @@ static void server_init(IRC_SERVER_REC *server) g_free(cmd); g_free(username); - if (conn->proxy != NULL && conn->proxy_string_after != NULL) { - cmd = g_strdup_printf(conn->proxy_string_after, conn->address, conn->port); - irc_send_cmd_now(server, cmd); - g_free(cmd); - } + if (conn->proxy && conn->proxy->send_string_after) + conn->proxy->send_string_after(conn->proxy, &send_info); server->isupport = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); From 3300e07f290f1e483419730bd070ae5d66d782d1 Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Tue, 26 Feb 2008 17:06:58 +0100 Subject: [PATCH 0015/1650] PROXY/SIMPLE: added simple proxy method This method implements the string + string_after mechanism implemented by previous irssi versions. To use, set * proxy_type to 'simple' or keep it empty * string + string_after in the known ways --- src/core/network-proxy-simple.c | 121 ++++++++++++++++++++++++++++++++ src/core/network-proxy-simple.h | 32 +++++++++ 2 files changed, 153 insertions(+) create mode 100644 src/core/network-proxy-simple.c create mode 100644 src/core/network-proxy-simple.h diff --git a/src/core/network-proxy-simple.c b/src/core/network-proxy-simple.c new file mode 100644 index 00000000..a7ac1fac --- /dev/null +++ b/src/core/network-proxy-simple.c @@ -0,0 +1,121 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * 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; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "module.h" +#include "network-proxy-simple.h" + +#include "network-proxy-priv.h" +#include "network.h" + +static void +network_proxy_simple_destroy(struct network_proxy *proxy) +{ + struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + + g_free((void *)self->password); + g_free((void *)self->string_after); + g_free((void *)self->string); + + _network_proxy_destroy(proxy); + + g_free(self); +} + +static struct network_proxy * +network_proxy_simple_clone(struct network_proxy const *proxy) +{ + struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + struct _network_proxy_simple *res; + + res = g_malloc0(sizeof *res); + + _network_proxy_clone(&res->proxy, &self->proxy); + + res->string = g_strdup(self->string); + res->string_after = g_strdup(self->string_after); + res->password = g_strdup(self->password); + return &res->proxy; +} + +static GIOChannel * +network_proxy_simple_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, + char const *address, int port) +{ + struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + + (void)address; + (void)port; + if (hint_ip) + return net_connect_ip(hint_ip, self->proxy.port, NULL); + else + return net_connect(self->proxy.host, self->proxy.port, NULL); +} + +static void +network_proxy_simple_send_string(struct network_proxy const *proxy, + struct network_proxy_send_string_info const *info) +{ + struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + char *cmd; + + if (self->password && self->password[0]) { + cmd = g_strdup_printf("PASS %s", self->password); + info->func(info->obj, cmd); + g_free(cmd); + } + + if (self->string && self->string[0]) { + cmd = g_strdup_printf(self->string, info->host, info->port); + info->func(info->obj, cmd); + g_free(cmd); + } +} + +static void +network_proxy_simple_send_string_after(struct network_proxy const *proxy, + struct network_proxy_send_string_info const *info) +{ + struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + char *cmd; + + if (self->string_after && self->string_after[0]) { + cmd = g_strdup_printf(self->string_after, info->host, info->port); + info->func(info->obj, cmd); + g_free(cmd); + } +} + +struct network_proxy * +_network_proxy_simple_create(void) +{ + struct _network_proxy_simple *res; + + res = g_malloc0(sizeof *res); + + _network_proxy_create(&res->proxy); + res->string = g_strdup(settings_get_str("proxy_string")); + res->string_after = g_strdup(settings_get_str("proxy_string_after")); + res->password = g_strdup(settings_get_str("proxy_password")); + + res->proxy.destroy = network_proxy_simple_destroy; + res->proxy.connect = network_proxy_simple_connect; + res->proxy.clone = network_proxy_simple_clone; + + res->proxy.send_string = network_proxy_simple_send_string; + res->proxy.send_string_after = network_proxy_simple_send_string_after; + + return &res->proxy; +} diff --git a/src/core/network-proxy-simple.h b/src/core/network-proxy-simple.h new file mode 100644 index 00000000..b2132cf2 --- /dev/null +++ b/src/core/network-proxy-simple.h @@ -0,0 +1,32 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * 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; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef H_IRSSI_SRC_CORE_PROXY_SIMPLE_H +#define H_IRSSI_SRC_CORE_PROXY_SIMPLE_H + +#include "network-proxy.h" + +struct _network_proxy_simple { + struct network_proxy proxy; + + char const *string_after; + char const *string; + char const *password; +}; + +struct network_proxy * _network_proxy_simple_create(void); + +#endif /* H_IRSSI_SRC_CORE_PROXY_SIMPLE_H */ From 47419298ef0f7f88ea8345726754a68ec66ad39d Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Tue, 26 Feb 2008 17:57:14 +0100 Subject: [PATCH 0016/1650] PROXY/HTTP: added methods for HTTP proxies This patch adds code for connecting through HTTP proxies. Open issues are: * support of proxy authentication * a possible DOS due to the usage of g_io_channel_read_line_string() which does not allow to specify a maximum length of line. To use this method: * set 'proxy_type' to 'http' --- src/core/network-proxy-http.c | 193 ++++++++++++++++++++++++++++++++++ src/core/network-proxy-http.h | 29 +++++ 2 files changed, 222 insertions(+) create mode 100644 src/core/network-proxy-http.c create mode 100644 src/core/network-proxy-http.h diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c new file mode 100644 index 00000000..3e79d784 --- /dev/null +++ b/src/core/network-proxy-http.c @@ -0,0 +1,193 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * 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; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "module.h" +#include "network-proxy-http.h" + +#include +#include +#include +#include + +#include "network.h" +#include "network-proxy-priv.h" + +static void +network_proxy_http_destroy(struct network_proxy *proxy) +{ + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + + g_free((void *)self->password); + _network_proxy_destroy(proxy); + + g_free(self); +} + +static struct network_proxy * +network_proxy_http_clone(struct network_proxy const *proxy) +{ + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + struct _network_proxy_http *res; + + res = g_malloc0(sizeof *res); + + _network_proxy_clone(&res->proxy, &self->proxy); + res->password = g_strdup(self->password); + return &res->proxy; +} + +static bool +send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, char const *address, uint16_t port) +{ + char port_str[6]; + + (void)proxy; + sprintf(port_str, "%u", port); + + if (!_network_proxy_send_all(ch, "CONNECT ", -1) || + !_network_proxy_send_all(ch, address, -1) || + !_network_proxy_send_all(ch, ":", -1) || + !_network_proxy_send_all(ch, port_str, -1) || + !_network_proxy_send_all(ch, " HTTP/1.0\r\n\r\n", -1) || + !_network_proxy_flush(ch)) + return -1; + + return true; +} + +static int +read_response(struct _network_proxy_http *proxy, GIOChannel *ch) +{ + GIOStatus status; + GString line = { .str = NULL }; + gsize term_pos; + GError *err = NULL; + int state = 0; + int rc = 0; + gchar *resp = NULL; + + (void)proxy; + for (;;) { + /* TODO: a malicious proxy can DOS us by sending much data + * without a line break */ + while ((status=g_io_channel_read_line_string(ch, &line, &term_pos, + &err))==G_IO_STATUS_AGAIN) + { + /* noop */ + } + + if (status!=G_IO_STATUS_NORMAL) { + g_warning("failed to read HTTP response: %s", err->message); + goto err; + } + + if (state==0) { + if (g_str_has_prefix(line.str, "HTTP/1.0 ")) { + resp = g_strndup(line.str+9, line.len-9-2); + rc = g_ascii_strtoull(resp, NULL, 10); + } else { + g_warning("unexpected HTTP response: '%s'", line.str); + goto err; + } + + /* state=1 ... read additional response headers + * (ignored for now) */ + state=1; + } + + if (line.len==2) /* only the \r\n terminators */ + break; + } + + if (rc!=200) + g_warning("unexpected HTTP response code: %s", resp); + + g_free(resp); + g_free(line.str); + return rc; + +err: + g_free(resp); + g_free(line.str); + return -1; +} + +static GIOChannel * +network_proxy_http_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, + char const *address, int port) +{ + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + GIOChannel *ch; + GIOFlags old_flags; + GError *err = NULL; + gchar const *line_term; + gint line_term_sz; + + if (hint_ip) + ch = net_connect_ip(hint_ip, self->proxy.port, NULL); + else + ch = net_connect(self->proxy.host, self->proxy.port, NULL); + + if (!ch) + return NULL; + + /* set \r\n line delims */ + line_term = g_io_channel_get_line_term(ch, &line_term_sz); + g_io_channel_set_line_term(ch, "\r\n", 2); + + /* set to non-blocking */ + old_flags = g_io_channel_get_flags(ch); + if (g_io_channel_set_flags(ch, old_flags & ~G_IO_FLAG_NONBLOCK, &err)!=G_IO_STATUS_NORMAL) + goto err; + + if (!send_connect(self, ch, address, port) || + read_response(self, ch)!=200) + goto err; + + if (g_io_channel_set_flags(ch, old_flags, &err)!=G_IO_STATUS_NORMAL) + goto err; + + g_io_channel_set_line_term(ch, line_term, line_term_sz); + return ch; +err: + if (err) { + g_warning("something went wrong while preparing HTTP proxy request: %s", + err->message); + g_error_free(err); + } + + net_disconnect(ch); + return NULL; + +} + + +struct network_proxy * +_network_proxy_http_create(void) +{ + struct _network_proxy_http *res; + + res = g_malloc0(sizeof *res); + + _network_proxy_create(&res->proxy); + res->password = g_strdup(settings_get_str("proxy_password")); + + res->proxy.destroy = network_proxy_http_destroy; + res->proxy.connect = network_proxy_http_connect; + res->proxy.clone = network_proxy_http_clone; + + return &res->proxy; +} diff --git a/src/core/network-proxy-http.h b/src/core/network-proxy-http.h new file mode 100644 index 00000000..92405fa6 --- /dev/null +++ b/src/core/network-proxy-http.h @@ -0,0 +1,29 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * 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; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef H_IRSSI_SRC_CORE_PROXY_HTTP_H +#define H_IRSSI_SRC_CORE_PROXY_HTTP_H + +#include "network-proxy.h" + +struct _network_proxy_http { + struct network_proxy proxy; + char const *password; +}; + +struct network_proxy * _network_proxy_http_create(void); + +#endif /* H_IRSSI_SRC_CORE_PROXY_HTTP_H */ From bb276c0b8023ae31805b06ba5e993125b2a27e28 Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Tue, 26 Feb 2008 18:04:40 +0100 Subject: [PATCH 0017/1650] PROXY/SOCKS5: added methods for SOCKS5 proxies This patch adds code for connecting through SOCKS5 proxies. It was primarily written for use with TOR, so there are some open issues: * it only allows to make proxy requests with full hostnames; ipv4/ipv6 is not supported * GSSAPI authentication (which is mentioned as mandatory in RFC 1928) is not implemented * plaintext authentication is untested To use it * set 'proxy_type' to 'socks5' --- src/core/network-proxy-socks5.c | 338 ++++++++++++++++++++++++++++++++ src/core/network-proxy-socks5.h | 31 +++ 2 files changed, 369 insertions(+) create mode 100644 src/core/network-proxy-socks5.c create mode 100644 src/core/network-proxy-socks5.h diff --git a/src/core/network-proxy-socks5.c b/src/core/network-proxy-socks5.c new file mode 100644 index 00000000..64a8f510 --- /dev/null +++ b/src/core/network-proxy-socks5.c @@ -0,0 +1,338 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * 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; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "module.h" +#include "network-proxy-socks5.h" + +#include +#include + +#include "network.h" +#include "network-proxy-priv.h" + +/* RFC 1928 */ +struct client_greeting +{ + uint8_t ver; + uint8_t nmethods; + uint8_t methods[]; +} __attribute__((__packed__)); + +struct server_greeting +{ + uint8_t ver; + uint8_t method; +} __attribute__((__packed__)); + +struct server_response_plain +{ + uint8_t ver; + uint8_t status; +} __attribute__((__packed__)); + +struct client_request +{ + uint8_t ver; + uint8_t cmd; + uint8_t rsv; + uint8_t atyp; + uint8_t dst[]; +} __attribute__((__packed__)); + +struct server_response +{ + uint8_t ver; + uint8_t rep; + uint8_t res; + uint8_t atyp; + uint8_t bnd[]; +} __attribute__((__packed__)); + +static void +network_proxy_socks5_destroy(struct network_proxy *proxy) +{ + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + + g_free((void *)self->password); + g_free((void *)self->username); + _network_proxy_destroy(proxy); + g_free(self); +} + +static struct network_proxy * +network_proxy_socks5_clone(struct network_proxy const *proxy) +{ + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + struct _network_proxy_socks5 *res; + + res = g_malloc0(sizeof *res); + + _network_proxy_clone(&res->proxy, &self->proxy); + res->username = g_strdup(self->username); + res->password = g_strdup(self->password); + return &res->proxy; +} + +static bool +socks5_connect_unauthorized(GIOChannel *ch) +{ + /* nothing to do here */ + (void)ch; + return true; +} + +/* TODO: test this method! */ +static bool +socks5_connect_plain(struct _network_proxy_socks5 const *proxy, GIOChannel *ch) +{ + uint8_t ver = 0x01; + uint8_t ulen = strlen(proxy->username); + uint8_t plen = proxy->password ? strlen(proxy->password) : 0; + struct server_response_plain resp; + + if (ulen==0 || + !_network_proxy_send_all(ch, &ver, sizeof ver) || + !_network_proxy_send_all(ch, &ulen, sizeof ulen) || + !_network_proxy_send_all(ch, proxy->username, ulen) || + !_network_proxy_send_all(ch, &plen, sizeof plen) || + (plen>0 && !_network_proxy_send_all(ch, proxy->password, plen)) || + !_network_proxy_flush(ch) || + !_network_proxy_recv_all(ch, &resp, sizeof resp)) + return false; + + if (resp.ver!=0x01) { + g_warning("unexpected plaintext response version %#04x", resp.ver); + return false; + } + + if (resp.status!=0x00) { + g_warning("socks5 authentication error (%#04x)", resp.status); + return false; + } + + return true; +} + +static bool +socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, + char const *address, uint16_t port) +{ + bool rc; + + struct server_greeting s_greeting; + struct server_response s_response; + + + /* Phase 1: exchange greeting */ + { + struct client_greeting c_greeting = { + .ver = 0x05, + .nmethods = proxy->username && proxy->username[0] ? 2 : 1 + }; + /* HACK: order is important because it depends upon + * c_greeting.nmethods */ + char const methods[] = { + 0x00, /* no authentication */ + 0x02 /* username/password */ + }; + if (!_network_proxy_send_all(ch, &c_greeting, sizeof c_greeting) || + !_network_proxy_send_all(ch, methods, c_greeting.nmethods) || + !_network_proxy_flush(ch) || + !_network_proxy_recv_all(ch, &s_greeting, sizeof s_greeting)) + goto err; + + if (s_greeting.ver!=5) { + g_warning("version mismatch during initial socks5 greeting; got version %#04x", + s_greeting.ver); + goto err; + } + } + + /* Phase 2: authentication */ + { + switch (s_greeting.method) { + case 0x00: rc = socks5_connect_unauthorized(ch); break; + case 0x02: rc = socks5_connect_plain(proxy, ch); break; + default: + g_warning("unsupported authentication method %#04x", s_greeting.method); + rc = false; + } + + if (!rc) + goto err; + } + + /* Phase 3: connection request */ + { + struct client_request c_request = { + .ver = 0x05, + .cmd = 0x01, /* CONNECT */ + .atyp = 0x03, /* domain name */ + }; + uint8_t address_len = strlen(address); + uint16_t dst_port = htons(port); + uint16_t bnd_port; + char bnd_address[257]; + + if (!_network_proxy_send_all(ch, &c_request, sizeof c_request) || + !_network_proxy_send_all(ch, &address_len, sizeof address_len) || + !_network_proxy_send_all(ch, address, address_len) || + !_network_proxy_send_all(ch, &dst_port, sizeof dst_port) || + !_network_proxy_flush(ch) || + !_network_proxy_recv_all(ch, &s_response, sizeof s_response)) + goto err; + + if (s_response.ver != 0x05) { + g_warning("version mismatch in socks5 response; got version %#04x", + s_response.ver); + goto err; + } + + rc = false; + switch (s_response.rep) { + case 0x00: rc = true; break; /* succeeded */ + case 0x01: g_warning("SOCKS5: general SOCKS server failure"); break; + case 0x02: g_warning("SOCKS5: connection not allowed by ruleset"); break; + case 0x03: g_warning("SOCKS5: Network unreachable"); break; + case 0x04: g_warning("SOCKS5: Host unreachable"); break; + case 0x05: g_warning("SOCKS5: Connection refused"); break; + case 0x06: g_warning("SOCKS5: TTL expired"); break; + case 0x07: g_warning("SOCKS5: Command not supported"); break; + case 0x08: g_warning("SOCKS5: Address type not supported"); break; + default: g_warning("SOCKS5: unknown error %#04x", s_response.rep); break; + } + + if (!rc) + goto err; + + switch(s_response.atyp) { + case 0x01: { + struct in_addr ip; + if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || + !inet_ntop(AF_INET, &ip, bnd_address, sizeof bnd_address)) + rc = false; + break; + } + + case 0x04: { + struct in6_addr ip; + if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || + !inet_ntop(AF_INET6, &ip, bnd_address, sizeof bnd_address)) + rc = false; + break; + } + + case 0x03: { + uint8_t tmp; + if (!_network_proxy_recv_all(ch, &tmp, sizeof tmp) || + tmp==0 || + !_network_proxy_recv_all(ch, &bnd_address, tmp)) + rc = false; + else + bnd_address[tmp] = '\0'; + } + + default: + g_warning("SOCKS5: unsupported address family in response: %#04x", + s_response.atyp); + rc = false; + } + + if (!rc || + !_network_proxy_recv_all(ch, &bnd_port, sizeof bnd_port)) + goto err; + + bnd_port = ntohs(bnd_port); + g_debug("SOCKS5: bound to %s:%u", bnd_address, bnd_port); + } + + return true; + +err: + g_warning("connecting through socks5 proxy failed"); + return false; +} + + +static GIOChannel * +network_proxy_socks5_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, + char const *address, int port) +{ + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + GIOChannel *ch; + + GIOFlags old_flags; + gchar const *old_enc; + gboolean old_buf; + GError *err = NULL; + + if (hint_ip) + ch = net_connect_ip(hint_ip, self->proxy.port, NULL); + else + ch = net_connect(self->proxy.host, self->proxy.port, NULL); + + if (!ch) + return NULL; + + old_enc = g_io_channel_get_encoding(ch); + old_flags = g_io_channel_get_flags(ch); + old_buf = g_io_channel_get_buffered(ch); + + if (g_io_channel_set_encoding(ch, NULL, &err)!=G_IO_STATUS_NORMAL || + g_io_channel_set_flags(ch, old_flags & ~G_IO_FLAG_NONBLOCK, &err)!=G_IO_STATUS_NORMAL) + goto err; + + g_io_channel_set_buffered(ch, false); + + if (!socks5_connect(self, ch, address, port)) + goto err; + + g_io_channel_set_buffered(ch, old_buf); + + if (g_io_channel_set_flags(ch, old_flags, &err) !=G_IO_STATUS_NORMAL || + g_io_channel_set_encoding(ch, old_enc, &err)!=G_IO_STATUS_NORMAL) + goto err; + + return ch; + +err: + if (err) { + g_warning("something went wrong while preparing SOCKS5 proxy request: %s", + err->message); + g_error_free(err); + } + + net_disconnect(ch); + return NULL; +} + +struct network_proxy * +_network_proxy_socks5_create(void) +{ + struct _network_proxy_socks5 *res; + + res = g_malloc0(sizeof *res); + + _network_proxy_create(&res->proxy); + res->username = g_strdup(settings_get_str("proxy_username")); + res->password = g_strdup(settings_get_str("proxy_password")); + + res->proxy.destroy = network_proxy_socks5_destroy; + res->proxy.connect = network_proxy_socks5_connect; + res->proxy.clone = network_proxy_socks5_clone; + + return &res->proxy; +} diff --git a/src/core/network-proxy-socks5.h b/src/core/network-proxy-socks5.h new file mode 100644 index 00000000..963bad3d --- /dev/null +++ b/src/core/network-proxy-socks5.h @@ -0,0 +1,31 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * 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; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef H_IRSSI_SRC_CORE_PROXY_SOCKS5_H +#define H_IRSSI_SRC_CORE_PROXY_SOCKS5_H + +#include "network-proxy.h" + +struct _network_proxy_socks5 { + struct network_proxy proxy; + + char const *username; + char const *password; +}; + +struct network_proxy * _network_proxy_socks5_create(void); + +#endif /* H_IRSSI_SRC_CORE_PROXY_SOCKS5_H */ From 2e8975270888cabd65683c070cb53412d43b5120 Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Tue, 26 Feb 2008 18:06:02 +0100 Subject: [PATCH 0018/1650] PROXY: merge proxy methods into buildsystem This patch adds the code and rules to build the various proxy methods. --- src/core/Makefile.am | 6 ++++++ src/core/network-proxy.c | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/core/Makefile.am b/src/core/Makefile.am index ce4b4bb6..c664739b 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -33,6 +33,12 @@ libcore_a_SOURCES = \ network-openssl.c \ network-proxy.c \ network-proxy.h \ + network-proxy-simple.c \ + network-proxy-simple.h \ + network-proxy-http.c \ + network-proxy-http.h \ + network-proxy-socks5.c \ + network-proxy-socks5.h \ network-proxy-priv.h \ nicklist.c \ nickmatch-cache.c \ diff --git a/src/core/network-proxy.c b/src/core/network-proxy.c index cedf96b5..cb5f9417 100644 --- a/src/core/network-proxy.c +++ b/src/core/network-proxy.c @@ -18,6 +18,9 @@ #include "network-proxy.h" #include +#include "network-proxy-simple.h" +#include "network-proxy-http.h" +#include "network-proxy-socks5.h" struct network_proxy * network_proxy_create(char const *type) @@ -25,6 +28,15 @@ network_proxy_create(char const *type) if (type==NULL) return NULL; + if (strcmp(type, "simple")==0 || type[0]=='\0') + return _network_proxy_simple_create(); + + if (strcmp(type, "http")==0) + return _network_proxy_http_create(); + + if (strcmp(type, "socks5")==0) + return _network_proxy_socks5_create(); + g_error("unsupported proxy type '%s'", type); return NULL; } From 9fcd69b9efbe64e0b9a8fa53f00ffcb968612fe7 Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Wed, 7 Apr 2010 09:50:12 +0200 Subject: [PATCH 0019/1650] http-proxy: fixed bad return value --- src/core/network-proxy-http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c index 3e79d784..dfed96d9 100644 --- a/src/core/network-proxy-http.c +++ b/src/core/network-proxy-http.c @@ -63,7 +63,7 @@ send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, char const *addr !_network_proxy_send_all(ch, port_str, -1) || !_network_proxy_send_all(ch, " HTTP/1.0\r\n\r\n", -1) || !_network_proxy_flush(ch)) - return -1; + return false; return true; } From d5727e1648d71dd46fedb3337dbc337e22eed11f Mon Sep 17 00:00:00 2001 From: hawken93 Date: Fri, 3 Oct 2014 17:34:24 +0200 Subject: [PATCH 0020/1650] Porting some stuff to modern git version --- src/core/network-openssl.c | 4 ++-- src/core/network.h | 2 +- src/core/servers.c | 5 +---- src/irc/core/irc-servers.c | 5 +++++ src/irc/core/irc-servers.h | 3 +++ 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 1ef2c99c..855333cd 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -551,8 +551,8 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ return gchan; } - -GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify) +GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, + IPADDR *ip, IPADDR *my_ip, SERVER_REC *server) { GIOChannel *handle, *ssl_handle; diff --git a/src/core/network.h b/src/core/network.h index af9c6983..910cc182 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -51,7 +51,7 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ GIOChannel *net_connect_ip(IPADDR const *ip, int port, IPADDR *my_ip); -GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify); +GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ GIOChannel *net_connect_proxy(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip); diff --git a/src/core/servers.c b/src/core/servers.c index 39b54f9a..c8b002bf 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -227,10 +227,7 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip, net_connect_proxy_ssl(server->connrec->proxy, server->connrec->address, port, ip, own_ip, - server->connrec->ssl_cert, - server->connrec->ssl_pkey, - server->connrec->ssl_cafile, - server->connrec->ssl_capath, server->connrec->ssl_verify) : + server->connrec) : net_connect_proxy(server->connrec->proxy, server->connrec->address, port, ip, own_ip); diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 1bf67ac3..daa85438 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -313,6 +313,11 @@ void irc_server_connect(SERVER_REC *server) } } +void irc_send_cmd_now_wrapper(void *server, const char *cmd) +{ + return irc_send_cmd_now((IRC_SERVER_REC *)server, cmd); +} + /* Returns TRUE if `command' is sent to `target' */ static int command_has_target(const char *cmd, const char *target) { diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h index 7e4eeabf..ac08d369 100644 --- a/src/irc/core/irc-servers.h +++ b/src/irc/core/irc-servers.h @@ -109,6 +109,7 @@ struct _IRC_SERVER_REC { SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn); void irc_server_connect(SERVER_REC *server); + /* Purge server output, either all or for specified target */ void irc_server_purge_output(IRC_SERVER_REC *server, const char *target); @@ -125,6 +126,8 @@ void irc_server_send_away(IRC_SERVER_REC *server, const char *reason); void irc_server_send_data(IRC_SERVER_REC *server, const char *data, int len); void irc_server_init_isupport(IRC_SERVER_REC *server); +void irc_send_cmd_now_wrapper(void *server, const char *cmd); + void irc_servers_start_cmd_timeout(void); void irc_servers_init(void); From f153922759eea4e28f92567fb5fa581bbaf7ee41 Mon Sep 17 00:00:00 2001 From: hawken93 Date: Fri, 3 Oct 2014 17:43:50 +0200 Subject: [PATCH 0021/1650] no patching unrelated stuff --- src/core/network.c | 2 +- src/core/network.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/network.c b/src/core/network.c index b65c376d..eba5a98a 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -170,7 +170,7 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) } /* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR const *ip, int port, IPADDR *my_ip) +GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) { union sockaddr_union so; int handle, ret, opt = 1; diff --git a/src/core/network.h b/src/core/network.h index 910cc182..3f138b82 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -50,10 +50,10 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ -GIOChannel *net_connect_ip(IPADDR const *ip, int port, IPADDR *my_ip); GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ +GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); GIOChannel *net_connect_proxy(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip); /* Connect to named UNIX socket */ GIOChannel *net_connect_unix(const char *path); From a35e5b4f9d423b93cba976ef5baddca7ea6fd60c Mon Sep 17 00:00:00 2001 From: hawken93 Date: Fri, 3 Oct 2014 23:30:37 +0200 Subject: [PATCH 0022/1650] Change coding style --- TODO | 5 + src/core/network-openssl.c | 2 +- src/core/network-proxy-http.c | 95 ++++++++--------- src/core/network-proxy-http.h | 24 +---- src/core/network-proxy-priv.h | 64 ++++------- src/core/network-proxy-simple.c | 88 ++++++++-------- src/core/network-proxy-simple.h | 28 ++--- src/core/network-proxy-socks5.c | 181 ++++++++++++++++---------------- src/core/network-proxy-socks5.h | 26 +---- src/core/network-proxy.c | 35 +++--- src/core/network-proxy.h | 53 +++------- src/core/network.c | 2 - src/core/network.h | 6 +- src/core/server-connect-rec.h | 2 +- 14 files changed, 257 insertions(+), 354 deletions(-) diff --git a/TODO b/TODO index 7d28a3f0..832c7e05 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,8 @@ + - New proxy code crashes if an invalid proxy_type setting is used + - Remove old socks code + - Lots of warnings at least when using socks5 + - Clean up coding style + 19:36 [IRCNet] [muzzy] more bugs in irssi, apparently the new version: foo splits out, bar joins, bar changes his nick to foo, foo splits again -> Glib warning "is already in split list (how?)" .. :) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 855333cd..177a40db 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -552,7 +552,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ return gchan; } GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, - IPADDR *ip, IPADDR *my_ip, SERVER_REC *server) + IPADDR *ip, IPADDR *my_ip, SERVER_REC *server) { GIOChannel *handle, *ssl_handle; diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c index dfed96d9..450e0784 100644 --- a/src/core/network-proxy-http.c +++ b/src/core/network-proxy-http.c @@ -1,18 +1,20 @@ -/* --*- c -*-- - * Copyright (C) 2008 Enrico Scholz - * - * 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; version 2 and/or 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +/* + network-proxy-http.c : irssi + + Copyright (C) 2008 Enrico Scholz + + 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; version 2 and/or 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ #include "module.h" #include "network-proxy-http.h" @@ -25,10 +27,9 @@ #include "network.h" #include "network-proxy-priv.h" -static void -network_proxy_http_destroy(struct network_proxy *proxy) +static void network_proxy_http_destroy(struct network_proxy *proxy) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); g_free((void *)self->password); _network_proxy_destroy(proxy); @@ -36,11 +37,10 @@ network_proxy_http_destroy(struct network_proxy *proxy) g_free(self); } -static struct network_proxy * -network_proxy_http_clone(struct network_proxy const *proxy) +static struct network_proxy *network_proxy_http_clone(const struct network_proxy *proxy) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); - struct _network_proxy_http *res; + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + struct _network_proxy_http *res; res = g_malloc0(sizeof *res); @@ -49,10 +49,10 @@ network_proxy_http_clone(struct network_proxy const *proxy) return &res->proxy; } -static bool -send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, char const *address, uint16_t port) +static bool send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, + const char *address, uint16_t port) { - char port_str[6]; + char port_str[6]; (void)proxy; sprintf(port_str, "%u", port); @@ -68,16 +68,15 @@ send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, char const *addr return true; } -static int -read_response(struct _network_proxy_http *proxy, GIOChannel *ch) +static int read_response(struct _network_proxy_http *proxy, GIOChannel *ch) { - GIOStatus status; - GString line = { .str = NULL }; - gsize term_pos; - GError *err = NULL; - int state = 0; - int rc = 0; - gchar *resp = NULL; + GIOStatus status; + GString line = { .str = NULL }; + gsize term_pos; + GError *err = NULL; + int state = 0; + int rc = 0; + gchar *resp = NULL; (void)proxy; for (;;) { @@ -125,16 +124,15 @@ err: return -1; } -static GIOChannel * -network_proxy_http_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, - char const *address, int port) +static GIOChannel *network_proxy_http_connect(const struct network_proxy *proxy, const IPADDR *hint_ip, + const char *address, int port) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); - GIOChannel *ch; - GIOFlags old_flags; - GError *err = NULL; - gchar const *line_term; - gint line_term_sz; + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + GIOChannel *ch; + GIOFlags old_flags; + GError *err = NULL; + const gchar *line_term; + gint line_term_sz; if (hint_ip) ch = net_connect_ip(hint_ip, self->proxy.port, NULL); @@ -171,23 +169,20 @@ err: net_disconnect(ch); return NULL; - } - -struct network_proxy * -_network_proxy_http_create(void) +struct network_proxy *_network_proxy_http_create(void) { - struct _network_proxy_http *res; + struct _network_proxy_http *res; res = g_malloc0(sizeof *res); _network_proxy_create(&res->proxy); - res->password = g_strdup(settings_get_str("proxy_password")); + res->password = g_strdup(settings_get_str("proxy_password")); res->proxy.destroy = network_proxy_http_destroy; res->proxy.connect = network_proxy_http_connect; - res->proxy.clone = network_proxy_http_clone; + res->proxy.clone = network_proxy_http_clone; return &res->proxy; } diff --git a/src/core/network-proxy-http.h b/src/core/network-proxy-http.h index 92405fa6..04bfdc43 100644 --- a/src/core/network-proxy-http.h +++ b/src/core/network-proxy-http.h @@ -1,29 +1,13 @@ -/* --*- c -*-- - * Copyright (C) 2008 Enrico Scholz - * - * 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; version 2 and/or 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - #ifndef H_IRSSI_SRC_CORE_PROXY_HTTP_H #define H_IRSSI_SRC_CORE_PROXY_HTTP_H #include "network-proxy.h" struct _network_proxy_http { - struct network_proxy proxy; - char const *password; + struct network_proxy proxy; + const char *password; }; -struct network_proxy * _network_proxy_http_create(void); +struct network_proxy *_network_proxy_http_create(void); -#endif /* H_IRSSI_SRC_CORE_PROXY_HTTP_H */ +#endif diff --git a/src/core/network-proxy-priv.h b/src/core/network-proxy-priv.h index 0a8f2449..5f632abb 100644 --- a/src/core/network-proxy-priv.h +++ b/src/core/network-proxy-priv.h @@ -1,19 +1,3 @@ -/* --*- c -*-- - * Copyright (C) 2008 Enrico Scholz - * - * 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; version 2 and/or 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - #ifndef H_IRSSI_SRC_CORE_PROXY_PRIV_H #define H_IRSSI_SRC_CORE_PROXY_PRIV_H @@ -26,38 +10,34 @@ (type *)( (char *)__mptr - offsetof(type,member) );}) -inline static void -_network_proxy_create(struct network_proxy *dst) +inline static void _network_proxy_create(struct network_proxy *dst) { - dst->port = settings_get_int("proxy_port"); - dst->host = g_strdup(settings_get_str("proxy_address")); + dst->port = settings_get_int("proxy_port"); + dst->host = g_strdup(settings_get_str("proxy_address")); } -inline static void -_network_proxy_clone(struct network_proxy *dst, struct network_proxy const *src) +inline static void _network_proxy_clone(struct network_proxy *dst, const struct network_proxy *src) { - dst->host = g_strdup(src->host); - dst->port = src->port; + dst->host = g_strdup(src->host); + dst->port = src->port; dst->destroy = src->destroy; dst->connect = src->connect; - dst->clone = src->clone; + dst->clone = src->clone; } -inline static void -_network_proxy_destroy(struct network_proxy *proxy) +inline static void _network_proxy_destroy(struct network_proxy *proxy) { g_free((void *)proxy->host); } -inline static bool -_network_proxy_send_all(GIOChannel *ch, void const *buf, ssize_t len) +inline static bool _network_proxy_send_all(GIOChannel *ch, const void *buf, ssize_t len) { - GError *err = NULL; - gsize written; - GIOStatus status; + GError *err = NULL; + gsize written; + GIOStatus status; while ((status=g_io_channel_write_chars(ch, buf, len, &written, &err))==G_IO_STATUS_AGAIN) @@ -74,15 +54,14 @@ _network_proxy_send_all(GIOChannel *ch, void const *buf, ssize_t len) return false; } -inline static bool -_network_proxy_recv_all(GIOChannel *ch, void *buf_v, size_t len) +inline static bool _network_proxy_recv_all(GIOChannel *ch, void *buf_v, size_t len) { - GError *err = NULL; - gchar *buf = buf_v; + GError *err = NULL; + gchar *buf = buf_v; while (len>0) { - GIOStatus status; - gsize l; + GIOStatus status; + gsize l; status = g_io_channel_read_chars(ch, buf, len, &l, &err); if (status==G_IO_STATUS_AGAIN) @@ -105,11 +84,10 @@ _network_proxy_recv_all(GIOChannel *ch, void *buf_v, size_t len) return false; } -inline static bool -_network_proxy_flush(GIOChannel *ch) +inline static bool _network_proxy_flush(GIOChannel *ch) { - GError *err = NULL; - GIOStatus status; + GError *err = NULL; + GIOStatus status; while ((status=g_io_channel_flush(ch, &err))==G_IO_STATUS_AGAIN) continue; @@ -125,4 +103,4 @@ _network_proxy_flush(GIOChannel *ch) return false; } -#endif /* H_IRSSI_SRC_CORE_PROXY_PRIV_H */ +#endif diff --git a/src/core/network-proxy-simple.c b/src/core/network-proxy-simple.c index a7ac1fac..e9f9e44c 100644 --- a/src/core/network-proxy-simple.c +++ b/src/core/network-proxy-simple.c @@ -1,18 +1,20 @@ -/* --*- c -*-- - * Copyright (C) 2008 Enrico Scholz - * - * 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; version 2 and/or 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +/* + network-proxy-simple.c : irssi + + Copyright (C) 2008 Enrico Scholz + + 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; version 2 and/or 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ #include "module.h" #include "network-proxy-simple.h" @@ -20,10 +22,9 @@ #include "network-proxy-priv.h" #include "network.h" -static void -network_proxy_simple_destroy(struct network_proxy *proxy) +static void network_proxy_simple_destroy(struct network_proxy *proxy) { - struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); g_free((void *)self->password); g_free((void *)self->string_after); @@ -34,27 +35,25 @@ network_proxy_simple_destroy(struct network_proxy *proxy) g_free(self); } -static struct network_proxy * -network_proxy_simple_clone(struct network_proxy const *proxy) +static struct network_proxy *network_proxy_simple_clone(const struct network_proxy *proxy) { - struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); - struct _network_proxy_simple *res; + struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + struct _network_proxy_simple *res; res = g_malloc0(sizeof *res); _network_proxy_clone(&res->proxy, &self->proxy); - res->string = g_strdup(self->string); + res->string = g_strdup(self->string); res->string_after = g_strdup(self->string_after); - res->password = g_strdup(self->password); + res->password = g_strdup(self->password); return &res->proxy; } -static GIOChannel * -network_proxy_simple_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, - char const *address, int port) +static GIOChannel *network_proxy_simple_connect(const struct network_proxy *proxy, const IPADDR *hint_ip, + char const *address, int port) { - struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); (void)address; (void)port; @@ -64,12 +63,11 @@ network_proxy_simple_connect(struct network_proxy const *proxy, IPADDR const *hi return net_connect(self->proxy.host, self->proxy.port, NULL); } -static void -network_proxy_simple_send_string(struct network_proxy const *proxy, - struct network_proxy_send_string_info const *info) +static void network_proxy_simple_send_string(const struct network_proxy *proxy, + const struct network_proxy_send_string_info *info) { - struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); - char *cmd; + struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + char *cmd; if (self->password && self->password[0]) { cmd = g_strdup_printf("PASS %s", self->password); @@ -84,12 +82,11 @@ network_proxy_simple_send_string(struct network_proxy const *proxy, } } -static void -network_proxy_simple_send_string_after(struct network_proxy const *proxy, - struct network_proxy_send_string_info const *info) +static void network_proxy_simple_send_string_after(const struct network_proxy *proxy, + const struct network_proxy_send_string_info *info) { - struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); - char *cmd; + struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + char *cmd; if (self->string_after && self->string_after[0]) { cmd = g_strdup_printf(self->string_after, info->host, info->port); @@ -98,23 +95,22 @@ network_proxy_simple_send_string_after(struct network_proxy const *proxy, } } -struct network_proxy * -_network_proxy_simple_create(void) +struct network_proxy *_network_proxy_simple_create(void) { - struct _network_proxy_simple *res; + struct _network_proxy_simple *res; res = g_malloc0(sizeof *res); _network_proxy_create(&res->proxy); - res->string = g_strdup(settings_get_str("proxy_string")); - res->string_after = g_strdup(settings_get_str("proxy_string_after")); - res->password = g_strdup(settings_get_str("proxy_password")); + res->string = g_strdup(settings_get_str("proxy_string")); + res->string_after = g_strdup(settings_get_str("proxy_string_after")); + res->password = g_strdup(settings_get_str("proxy_password")); res->proxy.destroy = network_proxy_simple_destroy; res->proxy.connect = network_proxy_simple_connect; - res->proxy.clone = network_proxy_simple_clone; + res->proxy.clone = network_proxy_simple_clone; - res->proxy.send_string = network_proxy_simple_send_string; + res->proxy.send_string = network_proxy_simple_send_string; res->proxy.send_string_after = network_proxy_simple_send_string_after; return &res->proxy; diff --git a/src/core/network-proxy-simple.h b/src/core/network-proxy-simple.h index b2132cf2..e55c3925 100644 --- a/src/core/network-proxy-simple.h +++ b/src/core/network-proxy-simple.h @@ -1,32 +1,16 @@ -/* --*- c -*-- - * Copyright (C) 2008 Enrico Scholz - * - * 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; version 2 and/or 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - #ifndef H_IRSSI_SRC_CORE_PROXY_SIMPLE_H #define H_IRSSI_SRC_CORE_PROXY_SIMPLE_H #include "network-proxy.h" struct _network_proxy_simple { - struct network_proxy proxy; + struct network_proxy proxy; - char const *string_after; - char const *string; - char const *password; + const char *string_after; + const char *string; + const char *password; }; -struct network_proxy * _network_proxy_simple_create(void); +struct network_proxy *_network_proxy_simple_create(void); -#endif /* H_IRSSI_SRC_CORE_PROXY_SIMPLE_H */ +#endif diff --git a/src/core/network-proxy-socks5.c b/src/core/network-proxy-socks5.c index 64a8f510..8f8fb308 100644 --- a/src/core/network-proxy-socks5.c +++ b/src/core/network-proxy-socks5.c @@ -1,18 +1,20 @@ -/* --*- c -*-- - * Copyright (C) 2008 Enrico Scholz - * - * 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; version 2 and/or 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +/* + network-proxy-socks5.c : irssi + + Copyright (C) 2008 Enrico Scholz + + 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; version 2 and/or 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ #include "module.h" #include "network-proxy-socks5.h" @@ -26,45 +28,44 @@ /* RFC 1928 */ struct client_greeting { - uint8_t ver; - uint8_t nmethods; - uint8_t methods[]; + uint8_t ver; + uint8_t nmethods; + uint8_t methods[]; } __attribute__((__packed__)); struct server_greeting { - uint8_t ver; - uint8_t method; + uint8_t ver; + uint8_t method; } __attribute__((__packed__)); struct server_response_plain { - uint8_t ver; - uint8_t status; + uint8_t ver; + uint8_t status; } __attribute__((__packed__)); struct client_request { - uint8_t ver; - uint8_t cmd; - uint8_t rsv; - uint8_t atyp; - uint8_t dst[]; + uint8_t ver; + uint8_t cmd; + uint8_t rsv; + uint8_t atyp; + uint8_t dst[]; } __attribute__((__packed__)); struct server_response { - uint8_t ver; - uint8_t rep; - uint8_t res; - uint8_t atyp; - uint8_t bnd[]; + uint8_t ver; + uint8_t rep; + uint8_t res; + uint8_t atyp; + uint8_t bnd[]; } __attribute__((__packed__)); -static void -network_proxy_socks5_destroy(struct network_proxy *proxy) +static void network_proxy_socks5_destroy(struct network_proxy *proxy) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); g_free((void *)self->password); g_free((void *)self->username); @@ -72,11 +73,10 @@ network_proxy_socks5_destroy(struct network_proxy *proxy) g_free(self); } -static struct network_proxy * -network_proxy_socks5_clone(struct network_proxy const *proxy) +static struct network_proxy *network_proxy_socks5_clone(const struct network_proxy *proxy) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); - struct _network_proxy_socks5 *res; + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + struct _network_proxy_socks5 *res; res = g_malloc0(sizeof *res); @@ -86,8 +86,7 @@ network_proxy_socks5_clone(struct network_proxy const *proxy) return &res->proxy; } -static bool -socks5_connect_unauthorized(GIOChannel *ch) +static bool socks5_connect_unauthorized(GIOChannel *ch) { /* nothing to do here */ (void)ch; @@ -95,13 +94,12 @@ socks5_connect_unauthorized(GIOChannel *ch) } /* TODO: test this method! */ -static bool -socks5_connect_plain(struct _network_proxy_socks5 const *proxy, GIOChannel *ch) +static bool socks5_connect_plain(const struct _network_proxy_socks5 *proxy, GIOChannel *ch) { - uint8_t ver = 0x01; - uint8_t ulen = strlen(proxy->username); - uint8_t plen = proxy->password ? strlen(proxy->password) : 0; - struct server_response_plain resp; + uint8_t ver = 0x01; + uint8_t ulen = strlen(proxy->username); + uint8_t plen = proxy->password ? strlen(proxy->password) : 0; + struct server_response_plain resp; if (ulen==0 || !_network_proxy_send_all(ch, &ver, sizeof ver) || @@ -126,30 +124,29 @@ socks5_connect_plain(struct _network_proxy_socks5 const *proxy, GIOChannel *ch) return true; } -static bool -socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, - char const *address, uint16_t port) +static bool socks5_connect(const struct _network_proxy_socks5 *proxy, GIOChannel *ch, + const char *address, uint16_t port) { - bool rc; + bool rc; - struct server_greeting s_greeting; - struct server_response s_response; + struct server_greeting s_greeting; + struct server_response s_response; /* Phase 1: exchange greeting */ { - struct client_greeting c_greeting = { - .ver = 0x05, + struct client_greeting c_greeting = { + .ver = 0x05, .nmethods = proxy->username && proxy->username[0] ? 2 : 1 }; /* HACK: order is important because it depends upon * c_greeting.nmethods */ - char const methods[] = { - 0x00, /* no authentication */ - 0x02 /* username/password */ + char const methods[] = { + 0x00, /* no authentication */ + 0x02 /* username/password */ }; if (!_network_proxy_send_all(ch, &c_greeting, sizeof c_greeting) || - !_network_proxy_send_all(ch, methods, c_greeting.nmethods) || + !_network_proxy_send_all(ch, methods, c_greeting.nmethods) || !_network_proxy_flush(ch) || !_network_proxy_recv_all(ch, &s_greeting, sizeof s_greeting)) goto err; @@ -177,22 +174,22 @@ socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, /* Phase 3: connection request */ { - struct client_request c_request = { - .ver = 0x05, - .cmd = 0x01, /* CONNECT */ - .atyp = 0x03, /* domain name */ + struct client_request c_request = { + .ver = 0x05, + .cmd = 0x01, /* CONNECT */ + .atyp = 0x03, /* domain name */ }; - uint8_t address_len = strlen(address); - uint16_t dst_port = htons(port); - uint16_t bnd_port; - char bnd_address[257]; + uint8_t address_len = strlen(address); + uint16_t dst_port = htons(port); + uint16_t bnd_port; + char bnd_address[257]; - if (!_network_proxy_send_all(ch, &c_request, sizeof c_request) || + if (!_network_proxy_send_all(ch, &c_request, sizeof c_request) || !_network_proxy_send_all(ch, &address_len, sizeof address_len) || - !_network_proxy_send_all(ch, address, address_len) || - !_network_proxy_send_all(ch, &dst_port, sizeof dst_port) || + !_network_proxy_send_all(ch, address, address_len) || + !_network_proxy_send_all(ch, &dst_port, sizeof dst_port) || !_network_proxy_flush(ch) || - !_network_proxy_recv_all(ch, &s_response, sizeof s_response)) + !_network_proxy_recv_all(ch, &s_response, sizeof s_response)) goto err; if (s_response.ver != 0x05) { @@ -212,7 +209,7 @@ socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, case 0x06: g_warning("SOCKS5: TTL expired"); break; case 0x07: g_warning("SOCKS5: Command not supported"); break; case 0x08: g_warning("SOCKS5: Address type not supported"); break; - default: g_warning("SOCKS5: unknown error %#04x", s_response.rep); break; + default: g_warning("SOCKS5: unknown error %#04x", s_response.rep); break; } if (!rc) @@ -220,8 +217,8 @@ socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, switch(s_response.atyp) { case 0x01: { - struct in_addr ip; - if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || + struct in_addr ip; + if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || !inet_ntop(AF_INET, &ip, bnd_address, sizeof bnd_address)) rc = false; break; @@ -229,14 +226,14 @@ socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, case 0x04: { struct in6_addr ip; - if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || + if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || !inet_ntop(AF_INET6, &ip, bnd_address, sizeof bnd_address)) rc = false; break; } case 0x03: { - uint8_t tmp; + uint8_t tmp; if (!_network_proxy_recv_all(ch, &tmp, sizeof tmp) || tmp==0 || !_network_proxy_recv_all(ch, &bnd_address, tmp)) @@ -267,17 +264,16 @@ err: } -static GIOChannel * -network_proxy_socks5_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, - char const *address, int port) +static GIOChannel *network_proxy_socks5_connect(const struct network_proxy *proxy, const IPADDR *hint_ip, + const char *address, int port) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); - GIOChannel *ch; + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + GIOChannel *ch; - GIOFlags old_flags; - gchar const *old_enc; - gboolean old_buf; - GError *err = NULL; + GIOFlags old_flags; + const gchar *old_enc; + gboolean old_buf; + GError *err = NULL; if (hint_ip) ch = net_connect_ip(hint_ip, self->proxy.port, NULL); @@ -287,9 +283,9 @@ network_proxy_socks5_connect(struct network_proxy const *proxy, IPADDR const *hi if (!ch) return NULL; - old_enc = g_io_channel_get_encoding(ch); + old_enc = g_io_channel_get_encoding(ch); old_flags = g_io_channel_get_flags(ch); - old_buf = g_io_channel_get_buffered(ch); + old_buf = g_io_channel_get_buffered(ch); if (g_io_channel_set_encoding(ch, NULL, &err)!=G_IO_STATUS_NORMAL || g_io_channel_set_flags(ch, old_flags & ~G_IO_FLAG_NONBLOCK, &err)!=G_IO_STATUS_NORMAL) @@ -319,20 +315,19 @@ err: return NULL; } -struct network_proxy * -_network_proxy_socks5_create(void) +struct network_proxy *_network_proxy_socks5_create(void) { - struct _network_proxy_socks5 *res; + struct _network_proxy_socks5 *res; res = g_malloc0(sizeof *res); _network_proxy_create(&res->proxy); - res->username = g_strdup(settings_get_str("proxy_username")); - res->password = g_strdup(settings_get_str("proxy_password")); + res->username = g_strdup(settings_get_str("proxy_username")); + res->password = g_strdup(settings_get_str("proxy_password")); res->proxy.destroy = network_proxy_socks5_destroy; res->proxy.connect = network_proxy_socks5_connect; - res->proxy.clone = network_proxy_socks5_clone; + res->proxy.clone = network_proxy_socks5_clone; return &res->proxy; } diff --git a/src/core/network-proxy-socks5.h b/src/core/network-proxy-socks5.h index 963bad3d..8dff6ed1 100644 --- a/src/core/network-proxy-socks5.h +++ b/src/core/network-proxy-socks5.h @@ -1,31 +1,15 @@ -/* --*- c -*-- - * Copyright (C) 2008 Enrico Scholz - * - * 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; version 2 and/or 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - #ifndef H_IRSSI_SRC_CORE_PROXY_SOCKS5_H #define H_IRSSI_SRC_CORE_PROXY_SOCKS5_H #include "network-proxy.h" struct _network_proxy_socks5 { - struct network_proxy proxy; + struct network_proxy proxy; - char const *username; - char const *password; + const char *username; + const char *password; }; -struct network_proxy * _network_proxy_socks5_create(void); +struct network_proxy *_network_proxy_socks5_create(void); -#endif /* H_IRSSI_SRC_CORE_PROXY_SOCKS5_H */ +#endif diff --git a/src/core/network-proxy.c b/src/core/network-proxy.c index cb5f9417..0deff1ee 100644 --- a/src/core/network-proxy.c +++ b/src/core/network-proxy.c @@ -1,18 +1,20 @@ -/* --*- c -*-- - * Copyright (C) 2008 Enrico Scholz - * - * 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; version 2 and/or 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +/* + network-proxy.c : irssi + + Copyright (C) 2008 Enrico Scholz + + 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; version 2 and/or 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ #include "module.h" @@ -22,8 +24,7 @@ #include "network-proxy-http.h" #include "network-proxy-socks5.h" -struct network_proxy * -network_proxy_create(char const *type) +struct network_proxy *network_proxy_create(const char *type) { if (type==NULL) return NULL; diff --git a/src/core/network-proxy.h b/src/core/network-proxy.h index cdc3d057..38fd1c82 100644 --- a/src/core/network-proxy.h +++ b/src/core/network-proxy.h @@ -1,19 +1,3 @@ -/* --*- c -*-- - * Copyright (C) 2008 Enrico Scholz - * - * 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; version 2 and/or 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - #ifndef H_IRSSI_SRC_CORE_PROXY_H #define H_IRSSI_SRC_CORE_PROXY_H @@ -22,22 +6,21 @@ /* helper structure for the send_string*() functions of the network_proxy * class */ -struct network_proxy_send_string_info -{ - char const *host; /* hostname of the IRC server */ - uint16_t port; /* portnumber of the IRC server */ +struct network_proxy_send_string_info { + const char *host; /* hostname of the IRC server */ + uint16_t port; /* portnumber of the IRC server */ /* function which is used to send string; usually irc_send_cmd_now() */ - void (*func)(void *obj, char const *); + void (*func)(void *obj, const char *); /* object for func */ - void *obj; + void *obj; }; struct network_proxy { /* destroys the network_proxy structure which must not be used anymore * after; this memberfunction is mandatory */ - void (*destroy)(struct network_proxy *); + void (*destroy)(struct network_proxy *); /* connects through the proxy; this memberfunction is mandatory * @@ -46,36 +29,34 @@ struct network_proxy { * \arg address the hostname where proxy shall connect to * \arg port port address where proxy shall connect to */ - GIOChannel * (*connect)(struct network_proxy const *, IPADDR const *hint_ip, - char const *address, int port); + GIOChannel *(*connect)(const struct *network_proxy, const IPADDR *hint_ip, + const char *address, int port); /* clones the given network_proxy object; this memberfunction is * mandatory */ - struct network_proxy * (*clone)(struct network_proxy const *); + struct network_proxy *(*clone)(const struct *network_proxy); /* sends a string after connection has been established but before IRC * authentication begins; this memberfunction is optional */ - void (*send_string)(struct network_proxy const *, - struct network_proxy_send_string_info const *); + void (*send_string)(const struct *network_proxy, + const struct *network_proxy_send_string_info); /* sends a string after connection IRC authentication suceeded; this * memberfunction is optional */ - void (*send_string_after)(struct network_proxy const *, - struct network_proxy_send_string_info const *); - + void (*send_string_after)(const struct *network_proxy, + const struct *network_proxy_send_string_info); /* hostname of proxy host */ - char const *host; + const char *host; /* portnumber of proxy */ - int port; + int port; }; /* factory method to create a proxy object based upon value of 'type' */ -struct network_proxy * network_proxy_create(char const *type); +struct network_proxy *network_proxy_create(const char *type); - -#endif /* H_IRSSI_SRC_CORE_PROXY_H */ +#endif diff --git a/src/core/network.c b/src/core/network.c index eba5a98a..75357f92 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -231,14 +231,12 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) GIOChannel *net_connect_proxy(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip) { - if (proxy) return proxy->connect(proxy, ip, host, port); else return net_connect_ip(ip, port, my_ip); } - /* Connect to named UNIX socket */ GIOChannel *net_connect_unix(const char *path) { diff --git a/src/core/network.h b/src/core/network.h index 3f138b82..b11d1ca2 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -50,11 +50,13 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ -GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); +GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, + IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); -GIOChannel *net_connect_proxy(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip); +GIOChannel *net_connect_proxy(struct network_proxy const *proxy, char const *host, int port, + IPADDR *ip, IPADDR *my_ip); /* Connect to named UNIX socket */ GIOChannel *net_connect_unix(const char *path); /* Disconnect socket */ diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h index ac99df8d..92a57a31 100644 --- a/src/core/server-connect-rec.h +++ b/src/core/server-connect-rec.h @@ -5,7 +5,7 @@ int chat_type; /* chat_protocol_lookup(xx) */ int refcount; -struct network_proxy *proxy; +struct network_proxy *proxy; unsigned short family; /* 0 = don't care, AF_INET or AF_INET6 */ char *tag; /* try to keep this tag when connected to server */ From 714b0241cbb85d98e7137fd513b2705617711aad Mon Sep 17 00:00:00 2001 From: hawken93 Date: Fri, 3 Oct 2014 23:41:57 +0200 Subject: [PATCH 0023/1650] Change coding style --- src/core/network-openssl.c | 2 +- src/core/network-proxy-http.c | 8 ++++---- src/core/network.c | 4 ++-- src/core/network.h | 4 ++-- src/irc/core/irc-servers.c | 10 +++++----- src/irc/core/irc-servers.h | 1 - 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 177a40db..0b0fb881 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -551,7 +551,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ return gchan; } -GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, +GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char *host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server) { GIOChannel *handle, *ssl_handle; diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c index 450e0784..623b3203 100644 --- a/src/core/network-proxy-http.c +++ b/src/core/network-proxy-http.c @@ -58,9 +58,9 @@ static bool send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, sprintf(port_str, "%u", port); if (!_network_proxy_send_all(ch, "CONNECT ", -1) || - !_network_proxy_send_all(ch, address, -1) || - !_network_proxy_send_all(ch, ":", -1) || - !_network_proxy_send_all(ch, port_str, -1) || + !_network_proxy_send_all(ch, address, -1) || + !_network_proxy_send_all(ch, ":", -1) || + !_network_proxy_send_all(ch, port_str, -1) || !_network_proxy_send_all(ch, " HTTP/1.0\r\n\r\n", -1) || !_network_proxy_flush(ch)) return false; @@ -96,7 +96,7 @@ static int read_response(struct _network_proxy_http *proxy, GIOChannel *ch) if (state==0) { if (g_str_has_prefix(line.str, "HTTP/1.0 ")) { resp = g_strndup(line.str+9, line.len-9-2); - rc = g_ascii_strtoull(resp, NULL, 10); + rc = g_ascii_strtoull(resp, NULL, 10); } else { g_warning("unexpected HTTP response: '%s'", line.str); goto err; diff --git a/src/core/network.c b/src/core/network.c index 75357f92..34319c58 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -228,8 +228,8 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) } /* Connect to socket */ -GIOChannel *net_connect_proxy(struct network_proxy const *proxy, - char const *host, int port, IPADDR *ip, IPADDR *my_ip) +GIOChannel *net_connect_proxy(const struct network_proxy *proxy, + const char *host, int port, IPADDR *ip, IPADDR *my_ip) { if (proxy) return proxy->connect(proxy, ip, host, port); diff --git a/src/core/network.h b/src/core/network.h index b11d1ca2..138dd31a 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -50,12 +50,12 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ -GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, +GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char c*host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); -GIOChannel *net_connect_proxy(struct network_proxy const *proxy, char const *host, int port, +GIOChannel *net_connect_proxy(const struct network_proxy *proxy, const char *host, int port, IPADDR *ip, IPADDR *my_ip); /* Connect to named UNIX socket */ GIOChannel *net_connect_unix(const char *path); diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index daa85438..ccd19aa8 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -196,11 +196,11 @@ static void server_init(IRC_SERVER_REC *server) IRC_SERVER_CONNECT_REC *conn; char *address, *ptr, *username, *cmd; GTimeVal now; - struct network_proxy_send_string_info const send_info = { - .host = server->connrec->address, - .port = server->connrec->port, - .func = irc_send_cmd_now_wrapper, - .obj = server + const struct network_proxy_send_string_info send_info = { + .host = server->connrec->address, + .port = server->connrec->port, + .func = irc_send_cmd_now_wrapper, + .obj = server }; g_return_if_fail(server != NULL); diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h index ac08d369..c6119df3 100644 --- a/src/irc/core/irc-servers.h +++ b/src/irc/core/irc-servers.h @@ -109,7 +109,6 @@ struct _IRC_SERVER_REC { SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn); void irc_server_connect(SERVER_REC *server); - /* Purge server output, either all or for specified target */ void irc_server_purge_output(IRC_SERVER_REC *server, const char *target); From 17ecad8285795728251fb45a0881ad56a6a1a32a Mon Sep 17 00:00:00 2001 From: hawken93 Date: Sat, 4 Oct 2014 00:52:26 +0200 Subject: [PATCH 0024/1650] Fixed stuff broken by the coding style cleanup --- src/core/network-proxy.h | 12 ++++++------ src/core/network.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/network-proxy.h b/src/core/network-proxy.h index 38fd1c82..c5ec02a2 100644 --- a/src/core/network-proxy.h +++ b/src/core/network-proxy.h @@ -29,25 +29,25 @@ struct network_proxy { * \arg address the hostname where proxy shall connect to * \arg port port address where proxy shall connect to */ - GIOChannel *(*connect)(const struct *network_proxy, const IPADDR *hint_ip, + GIOChannel *(*connect)(const struct network_proxy *, const IPADDR *hint_ip, const char *address, int port); /* clones the given network_proxy object; this memberfunction is * mandatory */ - struct network_proxy *(*clone)(const struct *network_proxy); + struct network_proxy *(*clone)(const struct network_proxy *); /* sends a string after connection has been established but before IRC * authentication begins; this memberfunction is optional */ - void (*send_string)(const struct *network_proxy, - const struct *network_proxy_send_string_info); + void (*send_string)(const struct network_proxy *, + const struct network_proxy_send_string_info *); /* sends a string after connection IRC authentication suceeded; this * memberfunction is optional */ - void (*send_string_after)(const struct *network_proxy, - const struct *network_proxy_send_string_info); + void (*send_string_after)(const struct network_proxy *, + const struct network_proxy_send_string_info *); /* hostname of proxy host */ const char *host; diff --git a/src/core/network.h b/src/core/network.h index 138dd31a..048ff71b 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -50,7 +50,7 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ -GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char c*host, int port, +GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char *host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ From 67d343fd3ad48a3096003350c4b715009616845a Mon Sep 17 00:00:00 2001 From: hawken93 Date: Sat, 4 Oct 2014 01:14:19 +0200 Subject: [PATCH 0025/1650] Fix compile warnings --- src/core/network.c | 2 +- src/core/network.h | 2 +- src/core/servers.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/network.c b/src/core/network.c index 34319c58..2969902a 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -170,7 +170,7 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) } /* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) +GIOChannel *net_connect_ip(const IPADDR *ip, int port, IPADDR *my_ip) { union sockaddr_union so; int handle, ret, opt = 1; diff --git a/src/core/network.h b/src/core/network.h index 048ff71b..0cdaaf1f 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -54,7 +54,7 @@ GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); +GIOChannel *net_connect_ip(const IPADDR *ip, int port, IPADDR *my_ip); GIOChannel *net_connect_proxy(const struct network_proxy *proxy, const char *host, int port, IPADDR *ip, IPADDR *my_ip); /* Connect to named UNIX socket */ diff --git a/src/core/servers.c b/src/core/servers.c index c8b002bf..3abd96bc 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -227,7 +227,7 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip, net_connect_proxy_ssl(server->connrec->proxy, server->connrec->address, port, ip, own_ip, - server->connrec) : + server) : net_connect_proxy(server->connrec->proxy, server->connrec->address, port, ip, own_ip); From c2505203d0e4f0eaaf202db6fb1f8cd9e1974ab6 Mon Sep 17 00:00:00 2001 From: hawken93 Date: Sat, 4 Oct 2014 23:22:50 +0200 Subject: [PATCH 0026/1650] Removed casts in g_free(), therefore also removed some const declarations --- src/core/network-proxy-http.c | 2 +- src/core/network-proxy-http.h | 2 +- src/core/network-proxy-priv.h | 2 +- src/core/network-proxy-simple.c | 6 +++--- src/core/network-proxy-simple.h | 6 +++--- src/core/network-proxy-socks5.c | 4 ++-- src/core/network-proxy-socks5.h | 4 ++-- src/core/network-proxy.h | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c index 623b3203..61d49208 100644 --- a/src/core/network-proxy-http.c +++ b/src/core/network-proxy-http.c @@ -31,7 +31,7 @@ static void network_proxy_http_destroy(struct network_proxy *proxy) { struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); - g_free((void *)self->password); + g_free(self->password); _network_proxy_destroy(proxy); g_free(self); diff --git a/src/core/network-proxy-http.h b/src/core/network-proxy-http.h index 04bfdc43..1f63d5e3 100644 --- a/src/core/network-proxy-http.h +++ b/src/core/network-proxy-http.h @@ -5,7 +5,7 @@ struct _network_proxy_http { struct network_proxy proxy; - const char *password; + char *password; }; struct network_proxy *_network_proxy_http_create(void); diff --git a/src/core/network-proxy-priv.h b/src/core/network-proxy-priv.h index 5f632abb..76d40f27 100644 --- a/src/core/network-proxy-priv.h +++ b/src/core/network-proxy-priv.h @@ -28,7 +28,7 @@ inline static void _network_proxy_clone(struct network_proxy *dst, const struct inline static void _network_proxy_destroy(struct network_proxy *proxy) { - g_free((void *)proxy->host); + g_free(proxy->host); } diff --git a/src/core/network-proxy-simple.c b/src/core/network-proxy-simple.c index e9f9e44c..289bb6ba 100644 --- a/src/core/network-proxy-simple.c +++ b/src/core/network-proxy-simple.c @@ -26,9 +26,9 @@ static void network_proxy_simple_destroy(struct network_proxy *proxy) { struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); - g_free((void *)self->password); - g_free((void *)self->string_after); - g_free((void *)self->string); + g_free(self->password); + g_free(self->string_after); + g_free(self->string); _network_proxy_destroy(proxy); diff --git a/src/core/network-proxy-simple.h b/src/core/network-proxy-simple.h index e55c3925..6c3c8281 100644 --- a/src/core/network-proxy-simple.h +++ b/src/core/network-proxy-simple.h @@ -6,9 +6,9 @@ struct _network_proxy_simple { struct network_proxy proxy; - const char *string_after; - const char *string; - const char *password; + char *string_after; + char *string; + char *password; }; struct network_proxy *_network_proxy_simple_create(void); diff --git a/src/core/network-proxy-socks5.c b/src/core/network-proxy-socks5.c index 8f8fb308..8c4eeaf7 100644 --- a/src/core/network-proxy-socks5.c +++ b/src/core/network-proxy-socks5.c @@ -67,8 +67,8 @@ static void network_proxy_socks5_destroy(struct network_proxy *proxy) { struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); - g_free((void *)self->password); - g_free((void *)self->username); + g_free(self->password); + g_free(self->username); _network_proxy_destroy(proxy); g_free(self); } diff --git a/src/core/network-proxy-socks5.h b/src/core/network-proxy-socks5.h index 8dff6ed1..058edaf5 100644 --- a/src/core/network-proxy-socks5.h +++ b/src/core/network-proxy-socks5.h @@ -6,8 +6,8 @@ struct _network_proxy_socks5 { struct network_proxy proxy; - const char *username; - const char *password; + char *username; + char *password; }; struct network_proxy *_network_proxy_socks5_create(void); diff --git a/src/core/network-proxy.h b/src/core/network-proxy.h index c5ec02a2..edd1a655 100644 --- a/src/core/network-proxy.h +++ b/src/core/network-proxy.h @@ -50,7 +50,7 @@ struct network_proxy { const struct network_proxy_send_string_info *); /* hostname of proxy host */ - const char *host; + char *host; /* portnumber of proxy */ int port; From c668e1add0cb51e854ad6d4262d01a69be75b110 Mon Sep 17 00:00:00 2001 From: hawken93 Date: Sun, 5 Oct 2014 01:02:50 +0200 Subject: [PATCH 0027/1650] add missing proxy_username setting --- src/core/servers-setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 87470266..19b1dc16 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -541,6 +541,7 @@ void servers_setup_init(void) settings_add_int("proxy", "proxy_port", 6667); settings_add_str("proxy", "proxy_string", "CONNECT %s %d"); settings_add_str("proxy", "proxy_string_after", ""); + settings_add_str("proxy", "proxy_username", ""); settings_add_str("proxy", "proxy_password", ""); settings_add_str("proxy", "proxy_type", "simple"); From 510fa50c071c18dcbc76afc0edb18f52302a0fc5 Mon Sep 17 00:00:00 2001 From: hawken93 Date: Sun, 5 Oct 2014 01:03:46 +0200 Subject: [PATCH 0028/1650] remove container_of, remove some underscores in the process --- src/core/network-proxy-http.c | 57 ++++++++++++++---------- src/core/network-proxy-http.h | 5 +-- src/core/network-proxy-priv.h | 10 +---- src/core/network-proxy-simple.c | 77 +++++++++++++++++++-------------- src/core/network-proxy-simple.h | 6 +-- src/core/network-proxy-socks5.c | 60 ++++++++++++++----------- src/core/network-proxy-socks5.h | 6 +-- src/core/network-proxy.c | 6 +-- src/core/network-proxy.h | 3 ++ 9 files changed, 128 insertions(+), 102 deletions(-) diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c index 61d49208..2eb504b5 100644 --- a/src/core/network-proxy-http.c +++ b/src/core/network-proxy-http.c @@ -29,27 +29,35 @@ static void network_proxy_http_destroy(struct network_proxy *proxy) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + struct network_proxy_http *self = (struct network_proxy_http *)proxy->privdata; g_free(self->password); - _network_proxy_destroy(proxy); g_free(self); + + _network_proxy_destroy(proxy); + + g_free(proxy); } static struct network_proxy *network_proxy_http_clone(const struct network_proxy *proxy) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); - struct _network_proxy_http *res; + struct network_proxy_http *self = (struct network_proxy_http *)proxy->privdata; + struct network_proxy_http *priv; + struct network_proxy *res; - res = g_malloc0(sizeof *res); + res = g_malloc0(sizeof(struct network_proxy)); - _network_proxy_clone(&res->proxy, &self->proxy); - res->password = g_strdup(self->password); - return &res->proxy; + _network_proxy_clone(res, proxy); + + priv = g_malloc0(sizeof(struct network_proxy_http)); + res->privdata = (void *)priv; + + priv->password = g_strdup(self->password); + return res; } -static bool send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, +static bool send_connect(struct network_proxy_http *proxy, GIOChannel *ch, const char *address, uint16_t port) { char port_str[6]; @@ -68,7 +76,7 @@ static bool send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, return true; } -static int read_response(struct _network_proxy_http *proxy, GIOChannel *ch) +static int read_response(struct network_proxy_http *proxy, GIOChannel *ch) { GIOStatus status; GString line = { .str = NULL }; @@ -127,7 +135,7 @@ err: static GIOChannel *network_proxy_http_connect(const struct network_proxy *proxy, const IPADDR *hint_ip, const char *address, int port) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + struct network_proxy_http *self = (struct network_proxy_http *)proxy->privdata; GIOChannel *ch; GIOFlags old_flags; GError *err = NULL; @@ -135,9 +143,9 @@ static GIOChannel *network_proxy_http_connect(const struct network_proxy *proxy, gint line_term_sz; if (hint_ip) - ch = net_connect_ip(hint_ip, self->proxy.port, NULL); + ch = net_connect_ip(hint_ip, proxy->port, NULL); else - ch = net_connect(self->proxy.host, self->proxy.port, NULL); + ch = net_connect(proxy->host, proxy->port, NULL); if (!ch) return NULL; @@ -171,18 +179,23 @@ err: return NULL; } -struct network_proxy *_network_proxy_http_create(void) +struct network_proxy *network_proxy_http_create(void) { - struct _network_proxy_http *res; + struct network_proxy *res; + struct network_proxy_http *priv; - res = g_malloc0(sizeof *res); + res = g_malloc0(sizeof(struct network_proxy)); - _network_proxy_create(&res->proxy); - res->password = g_strdup(settings_get_str("proxy_password")); + _network_proxy_create(res); - res->proxy.destroy = network_proxy_http_destroy; - res->proxy.connect = network_proxy_http_connect; - res->proxy.clone = network_proxy_http_clone; + priv = g_malloc0(sizeof(struct network_proxy_http)); + res->privdata = (void *)priv; - return &res->proxy; + priv->password = g_strdup(settings_get_str("proxy_password")); + + res->destroy = network_proxy_http_destroy; + res->connect = network_proxy_http_connect; + res->clone = network_proxy_http_clone; + + return res; } diff --git a/src/core/network-proxy-http.h b/src/core/network-proxy-http.h index 1f63d5e3..723aae43 100644 --- a/src/core/network-proxy-http.h +++ b/src/core/network-proxy-http.h @@ -3,11 +3,10 @@ #include "network-proxy.h" -struct _network_proxy_http { - struct network_proxy proxy; +struct network_proxy_http { char *password; }; -struct network_proxy *_network_proxy_http_create(void); +struct network_proxy *network_proxy_http_create(void); #endif diff --git a/src/core/network-proxy-priv.h b/src/core/network-proxy-priv.h index 76d40f27..d7b8050a 100644 --- a/src/core/network-proxy-priv.h +++ b/src/core/network-proxy-priv.h @@ -4,14 +4,10 @@ #include "settings.h" #include -/* stolen from linux kernel */ -#define container_of(ptr, type, member) __extension__ ({ \ - const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - - inline static void _network_proxy_create(struct network_proxy *dst) { + // TODO: Initialize all fields, to bring the struct to a known state + dst->privdata = NULL; dst->port = settings_get_int("proxy_port"); dst->host = g_strdup(settings_get_str("proxy_address")); } @@ -31,8 +27,6 @@ inline static void _network_proxy_destroy(struct network_proxy *proxy) g_free(proxy->host); } - - inline static bool _network_proxy_send_all(GIOChannel *ch, const void *buf, ssize_t len) { GError *err = NULL; diff --git a/src/core/network-proxy-simple.c b/src/core/network-proxy-simple.c index 289bb6ba..980215b5 100644 --- a/src/core/network-proxy-simple.c +++ b/src/core/network-proxy-simple.c @@ -24,49 +24,54 @@ static void network_proxy_simple_destroy(struct network_proxy *proxy) { - struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata; g_free(self->password); g_free(self->string_after); g_free(self->string); + g_free(self); + _network_proxy_destroy(proxy); - g_free(self); + // We are responsible for the whole proxy struct + g_free(proxy); } static struct network_proxy *network_proxy_simple_clone(const struct network_proxy *proxy) { - struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); - struct _network_proxy_simple *res; + struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata; + struct network_proxy *res; + struct network_proxy_simple *newself; - res = g_malloc0(sizeof *res); + // First make and set the parent struct + res = g_malloc0(sizeof(struct network_proxy)); + _network_proxy_clone(res, proxy); - _network_proxy_clone(&res->proxy, &self->proxy); + // Then allocate and set the private data + newself = g_malloc0(sizeof(struct network_proxy_simple)); + res->privdata = (void *)newself; - res->string = g_strdup(self->string); - res->string_after = g_strdup(self->string_after); - res->password = g_strdup(self->password); - return &res->proxy; + newself->string = g_strdup(self->string); + newself->string_after = g_strdup(self->string_after); + newself->password = g_strdup(self->password); + + return res; } -static GIOChannel *network_proxy_simple_connect(const struct network_proxy *proxy, const IPADDR *hint_ip, - char const *address, int port) +static GIOChannel *network_proxy_simple_connect(const struct network_proxy *proxy, + const IPADDR *hint_ip, char const *address, int port) { - struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); - - (void)address; - (void)port; if (hint_ip) - return net_connect_ip(hint_ip, self->proxy.port, NULL); + return net_connect_ip(hint_ip, proxy->port, NULL); else - return net_connect(self->proxy.host, self->proxy.port, NULL); + return net_connect(proxy->host, proxy->port, NULL); } static void network_proxy_simple_send_string(const struct network_proxy *proxy, const struct network_proxy_send_string_info *info) { - struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata; char *cmd; if (self->password && self->password[0]) { @@ -85,7 +90,7 @@ static void network_proxy_simple_send_string(const struct network_proxy *proxy, static void network_proxy_simple_send_string_after(const struct network_proxy *proxy, const struct network_proxy_send_string_info *info) { - struct _network_proxy_simple *self = container_of(proxy, struct _network_proxy_simple, proxy); + struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata; char *cmd; if (self->string_after && self->string_after[0]) { @@ -95,23 +100,29 @@ static void network_proxy_simple_send_string_after(const struct network_proxy *p } } -struct network_proxy *_network_proxy_simple_create(void) +struct network_proxy *network_proxy_simple_create(void) { - struct _network_proxy_simple *res; + struct network_proxy *proxy; + struct network_proxy_simple *self; - res = g_malloc0(sizeof *res); + proxy = g_malloc0(sizeof(struct network_proxy)); - _network_proxy_create(&res->proxy); - res->string = g_strdup(settings_get_str("proxy_string")); - res->string_after = g_strdup(settings_get_str("proxy_string_after")); - res->password = g_strdup(settings_get_str("proxy_password")); + // assume it could reset every variable to a known state + _network_proxy_create(proxy); - res->proxy.destroy = network_proxy_simple_destroy; - res->proxy.connect = network_proxy_simple_connect; - res->proxy.clone = network_proxy_simple_clone; + self = g_malloc0(sizeof(struct network_proxy_simple)); + proxy->privdata = (void *)self; - res->proxy.send_string = network_proxy_simple_send_string; - res->proxy.send_string_after = network_proxy_simple_send_string_after; + self->string = g_strdup(settings_get_str("proxy_string")); + self->string_after = g_strdup(settings_get_str("proxy_string_after")); + self->password = g_strdup(settings_get_str("proxy_password")); - return &res->proxy; + proxy->destroy = network_proxy_simple_destroy; + proxy->connect = network_proxy_simple_connect; + proxy->clone = network_proxy_simple_clone; + + proxy->send_string = network_proxy_simple_send_string; + proxy->send_string_after = network_proxy_simple_send_string_after; + + return proxy; } diff --git a/src/core/network-proxy-simple.h b/src/core/network-proxy-simple.h index 6c3c8281..010d8e4a 100644 --- a/src/core/network-proxy-simple.h +++ b/src/core/network-proxy-simple.h @@ -3,14 +3,12 @@ #include "network-proxy.h" -struct _network_proxy_simple { - struct network_proxy proxy; - +struct network_proxy_simple { char *string_after; char *string; char *password; }; -struct network_proxy *_network_proxy_simple_create(void); +struct network_proxy *network_proxy_simple_create(void); #endif diff --git a/src/core/network-proxy-socks5.c b/src/core/network-proxy-socks5.c index 8c4eeaf7..c3dc1e4c 100644 --- a/src/core/network-proxy-socks5.c +++ b/src/core/network-proxy-socks5.c @@ -65,25 +65,30 @@ struct server_response static void network_proxy_socks5_destroy(struct network_proxy *proxy) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + struct network_proxy_socks5 *self = (struct network_proxy_socks5 *)proxy->privdata; g_free(self->password); g_free(self->username); - _network_proxy_destroy(proxy); g_free(self); + _network_proxy_destroy(proxy); + g_free(proxy); } static struct network_proxy *network_proxy_socks5_clone(const struct network_proxy *proxy) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); - struct _network_proxy_socks5 *res; + struct network_proxy_socks5 *self = (struct network_proxy_socks5 *)proxy->privdata; + struct network_proxy_socks5 *priv; + struct network_proxy *res; - res = g_malloc0(sizeof *res); + res = g_malloc0(sizeof(struct network_proxy)); + _network_proxy_clone(res, proxy); - _network_proxy_clone(&res->proxy, &self->proxy); - res->username = g_strdup(self->username); - res->password = g_strdup(self->password); - return &res->proxy; + priv = g_malloc0(sizeof(struct network_proxy_socks5)); + res->privdata = (void *)priv; + + priv->username = g_strdup(self->username); + priv->password = g_strdup(self->password); + return res; } static bool socks5_connect_unauthorized(GIOChannel *ch) @@ -94,9 +99,9 @@ static bool socks5_connect_unauthorized(GIOChannel *ch) } /* TODO: test this method! */ -static bool socks5_connect_plain(const struct _network_proxy_socks5 *proxy, GIOChannel *ch) +static bool socks5_connect_plain(const struct network_proxy_socks5 *proxy, GIOChannel *ch) { - uint8_t ver = 0x01; + uint8_t ver = 0x01; uint8_t ulen = strlen(proxy->username); uint8_t plen = proxy->password ? strlen(proxy->password) : 0; struct server_response_plain resp; @@ -124,7 +129,7 @@ static bool socks5_connect_plain(const struct _network_proxy_socks5 *proxy, GIOC return true; } -static bool socks5_connect(const struct _network_proxy_socks5 *proxy, GIOChannel *ch, +static bool socks5_connect(const struct network_proxy_socks5 *proxy, GIOChannel *ch, const char *address, uint16_t port) { bool rc; @@ -267,7 +272,7 @@ err: static GIOChannel *network_proxy_socks5_connect(const struct network_proxy *proxy, const IPADDR *hint_ip, const char *address, int port) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + struct network_proxy_socks5 *self = (struct network_proxy_socks5 *)proxy->privdata; GIOChannel *ch; GIOFlags old_flags; @@ -276,9 +281,9 @@ static GIOChannel *network_proxy_socks5_connect(const struct network_proxy *prox GError *err = NULL; if (hint_ip) - ch = net_connect_ip(hint_ip, self->proxy.port, NULL); + ch = net_connect_ip(hint_ip, proxy->port, NULL); else - ch = net_connect(self->proxy.host, self->proxy.port, NULL); + ch = net_connect(proxy->host, proxy->port, NULL); if (!ch) return NULL; @@ -315,19 +320,24 @@ err: return NULL; } -struct network_proxy *_network_proxy_socks5_create(void) +struct network_proxy *network_proxy_socks5_create(void) { - struct _network_proxy_socks5 *res; + struct network_proxy *res; + struct network_proxy_socks5 *priv; - res = g_malloc0(sizeof *res); + res = g_malloc0(sizeof(struct network_proxy)); - _network_proxy_create(&res->proxy); - res->username = g_strdup(settings_get_str("proxy_username")); - res->password = g_strdup(settings_get_str("proxy_password")); + _network_proxy_create(res); - res->proxy.destroy = network_proxy_socks5_destroy; - res->proxy.connect = network_proxy_socks5_connect; - res->proxy.clone = network_proxy_socks5_clone; + priv = g_malloc0(sizeof(struct network_proxy_socks5)); + res->privdata = (void *)priv; - return &res->proxy; + priv->username = g_strdup(settings_get_str("proxy_username")); + priv->password = g_strdup(settings_get_str("proxy_password")); + + res->destroy = network_proxy_socks5_destroy; + res->connect = network_proxy_socks5_connect; + res->clone = network_proxy_socks5_clone; + + return res; } diff --git a/src/core/network-proxy-socks5.h b/src/core/network-proxy-socks5.h index 058edaf5..45431d3a 100644 --- a/src/core/network-proxy-socks5.h +++ b/src/core/network-proxy-socks5.h @@ -3,13 +3,11 @@ #include "network-proxy.h" -struct _network_proxy_socks5 { - struct network_proxy proxy; - +struct network_proxy_socks5 { char *username; char *password; }; -struct network_proxy *_network_proxy_socks5_create(void); +struct network_proxy *network_proxy_socks5_create(void); #endif diff --git a/src/core/network-proxy.c b/src/core/network-proxy.c index 0deff1ee..f056da6b 100644 --- a/src/core/network-proxy.c +++ b/src/core/network-proxy.c @@ -30,13 +30,13 @@ struct network_proxy *network_proxy_create(const char *type) return NULL; if (strcmp(type, "simple")==0 || type[0]=='\0') - return _network_proxy_simple_create(); + return network_proxy_simple_create(); if (strcmp(type, "http")==0) - return _network_proxy_http_create(); + return network_proxy_http_create(); if (strcmp(type, "socks5")==0) - return _network_proxy_socks5_create(); + return network_proxy_socks5_create(); g_error("unsupported proxy type '%s'", type); return NULL; diff --git a/src/core/network-proxy.h b/src/core/network-proxy.h index edd1a655..a9fbf936 100644 --- a/src/core/network-proxy.h +++ b/src/core/network-proxy.h @@ -18,6 +18,9 @@ struct network_proxy_send_string_info { }; struct network_proxy { + /* Contains private data for the chosen proxy type */ + void *privdata; + /* destroys the network_proxy structure which must not be used anymore * after; this memberfunction is mandatory */ void (*destroy)(struct network_proxy *); From df1df75ca2cc461360e336ce83052366002b1b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sat, 11 Oct 2014 10:44:46 +0200 Subject: [PATCH 0029/1650] Prepare for 0.8.17 --- NEWS | 3 ++- configure.ac | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 8f9e36a1..ac002150 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -v0.8.17-head 2014-XX-XX The Irssi team +v0.8.17 2014-10-11 The Irssi team + Document that SSL connections aren't properly handled during /UPGRADE. See Github PR #39. + Synchronize scripts with scripts.irssi.org. + Performance enhancement of the nicklist as well as the window_item_find function. See Github PR #24. @@ -19,6 +19,7 @@ v0.8.17-head 2014-XX-XX The Irssi team - Fixed gui_printtext_after and term_refresh_*() visibility. See Github PR #22. - Fixed issue where UTF-8 characters was corrupted once for every 32k text. See Github PR #12. - Fixed redrawing issue with right-aligned statusbar. + - Fixed use-after-free bug with cached settings values. See Github PR #147. v0.8.16 2014-05-28 The Irssi team + Add -noautosendcmd to /SERVER and /CONNECT. Passing this option will diff --git a/configure.ac b/configure.ac index 2a7bee0d..f148885c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(irssi, 0.8.17-head) +AC_INIT(irssi, 0.8.17) AC_CONFIG_SRCDIR([src]) AC_CONFIG_AUX_DIR(build-aux) AC_PREREQ(2.50) From 3f50b8f2ad7e9a10aab1ff88c58141563c4dd68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sat, 11 Oct 2014 11:12:43 +0200 Subject: [PATCH 0030/1650] HEAD's now 0.8.18-head. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f148885c..477f8c4d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(irssi, 0.8.17) +AC_INIT(irssi, 0.8.18-head) AC_CONFIG_SRCDIR([src]) AC_CONFIG_AUX_DIR(build-aux) AC_PREREQ(2.50) From 10078407f6cab2e25e35be37dba903d91126f561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sat, 11 Oct 2014 12:13:22 +0200 Subject: [PATCH 0031/1650] Remove unnecessary NULL check Fixes: #135 --- src/core/servers.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/servers.c b/src/core/servers.c index 06f82d4d..6eaad191 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -218,9 +218,7 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip, return; if (ip != NULL) { - own_ip = ip == NULL ? NULL : - (IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : - server->connrec->own_ip4); + own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4; port = server->connrec->proxy != NULL ? server->connrec->proxy_port : server->connrec->port; handle = server->connrec->use_ssl ? From 971b1e57ab762fce967f15c28e7b6e6a826a0188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sat, 11 Oct 2014 12:16:43 +0200 Subject: [PATCH 0032/1650] Add header for v0.8.18-head --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index ac002150..5d313da1 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +v0.8.18-head 2014-XX-YY The Irssi team + v0.8.17 2014-10-11 The Irssi team + Document that SSL connections aren't properly handled during /UPGRADE. See Github PR #39. + Synchronize scripts with scripts.irssi.org. From 8bd575df2ec0d4a17b6f59116d555b64f5bb1312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Wed, 15 Oct 2014 10:00:30 +0200 Subject: [PATCH 0033/1650] Disable SSLv3 --- src/core/network-openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 768fd540..e16403ec 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -475,7 +475,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ g_error("Could not allocate memory for SSL context"); return NULL; } - SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); SSL_CTX_set_default_passwd_cb(ctx, get_pem_password_callback); SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)mypass); From 136efda1bc54a49c89bbb3967d55b735e2788f72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Wed, 15 Oct 2014 20:14:17 +0200 Subject: [PATCH 0034/1650] Add NEWS entry on SSLv3 --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 5d313da1..de36d195 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,5 @@ v0.8.18-head 2014-XX-YY The Irssi team + + Disable SSLv3 due to the POODLE vulnerability. v0.8.17 2014-10-11 The Irssi team + Document that SSL connections aren't properly handled during /UPGRADE. See Github PR #39. From 7847bdf67cab8579679d830787929468cbc45139 Mon Sep 17 00:00:00 2001 From: dequis Date: Wed, 15 Oct 2014 23:52:55 -0300 Subject: [PATCH 0035/1650] Tiny fix to the param order in the /SERVER REMOVE help --- docs/help/in/server.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/help/in/server.in b/docs/help/in/server.in index 5628b19f..809c5acd 100644 --- a/docs/help/in/server.in +++ b/docs/help/in/server.in @@ -61,7 +61,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 REMOVE -network Freenode orwell.freenode.net + /SERVER REMOVE orwell.freenode.net Freenode /SERVER PURGE /SERVER PURGE orwell.freenode.net From f81a54b937b16ebabc05a01d3053a49b3341ac8c Mon Sep 17 00:00:00 2001 From: Sebastian Thorarensen Date: Sat, 11 Oct 2014 18:47:39 +0200 Subject: [PATCH 0036/1650] Try to split long lines on spaces Try to split long lines on spaces to avoid words being splitted. This can be turned off with the option `split_line_on_space'. The code assumes that the terminal encoding has ASCII spaces. --- NEWS | 2 ++ src/core/misc.c | 33 ++++++++++++++++++++++----------- src/core/misc.h | 2 +- src/core/recode.c | 20 +++++++++++++++++--- src/core/recode.h | 2 +- src/irc/core/irc-servers.c | 4 +++- 6 files changed, 46 insertions(+), 17 deletions(-) diff --git a/NEWS b/NEWS index de36d195..70717965 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,7 @@ v0.8.18-head 2014-XX-YY The Irssi team + Disable SSLv3 due to the POODLE vulnerability. + + Try to split long lines on spaces to avoid words being splitted. Adds + a new option: 'split_line_on_space' which defaults to on. v0.8.17 2014-10-11 The Irssi team + Document that SSL connections aren't properly handled during /UPGRADE. See Github PR #39. diff --git a/src/core/misc.c b/src/core/misc.c index 5e6087cb..586e4f7c 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -967,19 +967,30 @@ char *ascii_strdown(char *str) return str; } -char **strsplit_len(const char *str, int len) +char **strsplit_len(const char *str, int len, gboolean onspace) { - char **ret; - size_t total_len = strlen(str); - int n = total_len / len; - int i; + char **ret = g_new(char *, 1); + int n; + int offset; - if (total_len % len) - n++; - - ret = g_new(char *, n + 1); - for (i = 0; i < n; i++, str += len) - ret[i] = g_strndup(str, len); + for (n = 0; *str != '\0'; n++, str += MIN(len - offset, strlen(str))) { + offset = 0; + if (onspace) { + /* + * Try to find a space to split on and leave + * the space on the previous line. + */ + int i; + for (i = 0; i < len; i++) { + if (str[len-1-i] == ' ') { + offset = i; + break; + } + } + } + ret[n] = g_strndup(str, len - offset); + ret = g_renew(char *, ret, n + 2); + } ret[n] = NULL; return ret; diff --git a/src/core/misc.h b/src/core/misc.h index 8fb5078f..c6369489 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -116,6 +116,6 @@ uoff_t str_to_uofft(const char *str); int find_substr(const char *list, const char *item); /* split `str' into `len' sized substrings */ -char **strsplit_len(const char *str, int len); +char **strsplit_len(const char *str, int len, gboolean onspace); #endif diff --git a/src/core/recode.c b/src/core/recode.c index 029d7ff1..d001a46a 100644 --- a/src/core/recode.c +++ b/src/core/recode.c @@ -183,7 +183,7 @@ char *recode_out(const SERVER_REC *server, const char *str, const char *target) } char **recode_split(const SERVER_REC *server, const char *str, - const char *target, int len) + const char *target, int len, gboolean onspace) { GIConv cd = (GIConv)-1; const char *from = translit_charset; @@ -219,7 +219,7 @@ char **recode_split(const SERVER_REC *server, const char *str, cd = g_iconv_open(to, from); if (cd == (GIConv)-1) { /* Fall back to splitting by byte. */ - ret = strsplit_len(str, len); + ret = strsplit_len(str, len, onspace); goto out; } @@ -235,11 +235,25 @@ char **recode_split(const SERVER_REC *server, const char *str, */ ret[n] = NULL; g_strfreev(ret); - ret = strsplit_len(str, len); + ret = strsplit_len(str, len, onspace); goto out; } /* Outbuf overflowed, split the input string. */ + if (onspace) { + /* + * Try to find a space to split on and leave + * the space on the previous line. + */ + int i; + for (i = 0; i < inbuf - previnbuf; i++) { + if (previnbuf[inbuf-previnbuf-1-i] == ' ') { + inbuf -= i; + inbytesleft += i; + break; + } + } + } ret[n++] = g_strndup(previnbuf, inbuf - previnbuf); ret = g_renew(char *, ret, n + 1); previnbuf = inbuf; diff --git a/src/core/recode.h b/src/core/recode.h index b70ec630..719e8f54 100644 --- a/src/core/recode.h +++ b/src/core/recode.h @@ -4,7 +4,7 @@ char *recode_in (const SERVER_REC *server, const char *str, const char *target); char *recode_out (const SERVER_REC *server, const char *str, const char *target); char **recode_split(const SERVER_REC *server, const char *str, - const char *target, int len); + const char *target, int len, gboolean onspace); gboolean is_valid_charset(const char *charset); gboolean is_utf8(void); void recode_update_charset(void); diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 27878989..baf8a0d2 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -85,6 +85,7 @@ static char **split_line(const SERVER_REC *server, const char *line, { const char *start = settings_get_str("split_line_start"); const char *end = settings_get_str("split_line_end"); + gboolean onspace = settings_get_bool("split_line_on_space"); char *recoded_start = recode_out(server, start, target); char *recoded_end = recode_out(server, end, target); char **lines; @@ -103,7 +104,7 @@ static char **split_line(const SERVER_REC *server, const char *line, return NULL; } - lines = recode_split(server, line, target, len); + lines = recode_split(server, line, target, len, onspace); for (i = 0; lines[i] != NULL; i++) { if (i != 0 && *start != '\0') { /* Not the first line. */ @@ -972,6 +973,7 @@ void irc_servers_init(void) settings_add_str("misc", "usermode", DEFAULT_USER_MODE); settings_add_str("misc", "split_line_start", ""); settings_add_str("misc", "split_line_end", ""); + settings_add_bool("misc", "split_line_on_space", TRUE); settings_add_time("flood", "cmd_queue_speed", DEFAULT_CMD_QUEUE_SPEED); settings_add_int("flood", "cmds_max_at_once", DEFAULT_CMDS_MAX_AT_ONCE); From 7938af8092fc5bc682bb9017b87eeb7ce0a2e428 Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Mon, 20 Oct 2014 21:11:20 +0100 Subject: [PATCH 0037/1650] Actually fix the params for /SERVER REMOVE --- docs/help/in/server.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/help/in/server.in b/docs/help/in/server.in index 809c5acd..d8bcb9a7 100644 --- a/docs/help/in/server.in +++ b/docs/help/in/server.in @@ -61,7 +61,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 REMOVE orwell.freenode.net Freenode + /SERVER REMOVE orwell.freenode.net 6667 Freenode /SERVER PURGE /SERVER PURGE orwell.freenode.net From 8e29a70a82ee3dd02f996a7bd3a86954564c6b4a Mon Sep 17 00:00:00 2001 From: mjn Date: Sat, 25 Oct 2014 17:00:27 +0200 Subject: [PATCH 0038/1650] Update old bug URLs At some point in the past few years, Flyspray changed its URL scheme from id=nnn to task_id=nnn, which broke some old comments in the source. Update those comments to URLs that still work. --- src/fe-common/irc/fe-whois.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fe-common/irc/fe-whois.c b/src/fe-common/irc/fe-whois.c index 35f99375..a9c3775e 100644 --- a/src/fe-common/irc/fe-whois.c +++ b/src/fe-common/irc/fe-whois.c @@ -92,7 +92,7 @@ static void event_whois_oper(IRC_SERVER_REC *server, const char *data) params = event_get_params(data, 3, NULL, &nick, &type); - /* Bugfix: http://bugs.irssi.org/?do=details&id=99 + /* Bugfix: http://bugs.irssi.org/?do=details&task_id=99 * Author: Geert Hauwaerts * Date: Wed Sep 15 20:17:24 CEST 2004 */ @@ -410,7 +410,7 @@ void fe_whois_init(void) signal_add("event 311", (SIGNAL_FUNC) event_whois); signal_add("event 312", (SIGNAL_FUNC) event_whois_server); /* readding this events fixes the printing of /whois -yes * - Bug http://bugs.irssi.org/?do=details&id=123 */ + Bug http://bugs.irssi.org/?do=details&task_id=123 */ signal_add("event 317", (SIGNAL_FUNC) event_whois_idle); signal_add("event 319", (SIGNAL_FUNC) event_whois_channels); signal_add("event 313", (SIGNAL_FUNC) event_whois_oper); From 1edfcedda1105d79fa6b92d77a8fb60f296abe1e Mon Sep 17 00:00:00 2001 From: dequis Date: Sun, 26 Oct 2014 00:12:30 -0300 Subject: [PATCH 0039/1650] Receive 'self messages' in the right query window Original patch by hondza , from FS#833. I applied several needed style changes, and rebased to current HEAD. This implements the IRCv3.2 self-message extension partially (we can't announce its support through CAP yet). This is also the format used by the 'privmsg' znc module, and is already implemented by several other clients. --- src/fe-common/core/fe-messages.c | 19 ++++++++++++++----- src/fe-common/core/fe-queries.c | 7 +++++-- src/fe-common/irc/fe-irc-messages.c | 27 +++++++++++++++++++-------- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index 97f3d84d..1d44bdd9 100644 --- a/src/fe-common/core/fe-messages.c +++ b/src/fe-common/core/fe-messages.c @@ -242,13 +242,16 @@ static void sig_message_public(SERVER_REC *server, const char *msg, } static void sig_message_private(SERVER_REC *server, const char *msg, - const char *nick, const char *address) + const char *nick, const char *address, const char *target) { QUERY_REC *query; char *freemsg = NULL; int level = MSGLEVEL_MSGS; - query = query_find(server, nick); + /* own message returned by bouncer? */ + int own = (!strcmp(nick, server->nick)); + + query = query_find(server, own ? target : nick); if (settings_get_bool("emphasis")) msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg); @@ -256,9 +259,15 @@ static void sig_message_private(SERVER_REC *server, const char *msg, if (ignore_check(server, nick, address, NULL, msg, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; - printformat(server, nick, level, - query == NULL ? TXT_MSG_PRIVATE : - TXT_MSG_PRIVATE_QUERY, nick, address, msg); + if (own) { + printformat(server, target, level, + query == NULL ? TXT_OWN_MSG_PRIVATE : + TXT_OWN_MSG_PRIVATE_QUERY, target, msg, server->nick); + } else { + printformat(server, nick, level, + query == NULL ? TXT_MSG_PRIVATE : + TXT_MSG_PRIVATE_QUERY, nick, address, msg); + } g_free_not_null(freemsg); } diff --git a/src/fe-common/core/fe-queries.c b/src/fe-common/core/fe-queries.c index 7599fb23..5cdf87ee 100644 --- a/src/fe-common/core/fe-queries.c +++ b/src/fe-common/core/fe-queries.c @@ -326,12 +326,15 @@ static int sig_query_autoclose(void) } static void sig_message_private(SERVER_REC *server, const char *msg, - const char *nick, const char *address) + const char *nick, const char *address, const char *target) { QUERY_REC *query; + /* own message returned by bouncer? */ + int own = (!strcmp(nick, server->nick)); + /* create query window if needed */ - query = privmsg_get_query(server, nick, FALSE, MSGLEVEL_MSGS); + query = privmsg_get_query(server, own ? target : nick, FALSE, MSGLEVEL_MSGS); /* reset the query's last_unread_msg timestamp */ if (query != NULL) diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index 0c83a531..e0849c75 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -160,6 +160,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, const char *oldtarget; char *freemsg = NULL; int level; + int own = FALSE; oldtarget = target; target = skip_target(IRC_SERVER(server), target); @@ -174,10 +175,12 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; - if (ischannel(*target)) + if (ischannel(*target)) { item = irc_channel_find(server, target); - else - item = privmsg_get_query(SERVER(server), nick, FALSE, level); + } else { + own = (!strcmp(nick, server->nick)); + item = privmsg_get_query(SERVER(server), own ? nick : target, FALSE, level); + } if (settings_get_bool("emphasis")) msg = freemsg = expand_emphasis(item, msg); @@ -195,11 +198,19 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, nick, oldtarget, msg); } } else { - /* private action */ - printformat(server, nick, MSGLEVEL_ACTIONS | MSGLEVEL_MSGS, - item == NULL ? IRCTXT_ACTION_PRIVATE : - IRCTXT_ACTION_PRIVATE_QUERY, - nick, address == NULL ? "" : address, msg); + if (own) { + /* own action bounced */ + printformat(server, target, + MSGLEVEL_ACTIONS | MSGLEVEL_MSGS, + item != NULL && oldtarget == target ? IRCTXT_OWN_ACTION : IRCTXT_OWN_ACTION_TARGET, + server->nick, msg, oldtarget); + } else { + /* private action */ + printformat(server, nick, MSGLEVEL_ACTIONS | MSGLEVEL_MSGS, + item == NULL ? IRCTXT_ACTION_PRIVATE : + IRCTXT_ACTION_PRIVATE_QUERY, + nick, address == NULL ? "" : address, msg); + } } g_free_not_null(freemsg); From 3ea2a8dab8212d5155014a9aa1aee3f2e456cd94 Mon Sep 17 00:00:00 2001 From: Matt Lewandowsky Date: Mon, 27 Oct 2014 03:44:28 -0700 Subject: [PATCH 0040/1650] Remove duplicate example from ignore.in Duplicated line inserted in commit 66f5fb6. Reported by @sharethebug on IRC. --- docs/help/in/ignore.in | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/help/in/ignore.in b/docs/help/in/ignore.in index 8c2b1c90..b0a547c1 100644 --- a/docs/help/in/ignore.in +++ b/docs/help/in/ignore.in @@ -41,7 +41,6 @@ /IGNORE #irssi NO_ACT JOINS PARTS QUITS /IGNORE mike NO_ACT -MSGS /IGNORE -regexp -pattern - /IGNORE mike NO_ACT -MSGS %9See also:%9 ACCEPT, SILENCE, UNIGNORE From 77a90effe305a0d39ce33fe187bb2e0c0125da36 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Tue, 28 Oct 2014 10:50:26 +0100 Subject: [PATCH 0041/1650] Fix reset of attributes with ansi reported by Christopher Ohlsson (dmnc) --- src/fe-common/core/formats.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index 375b00eb..ccf48394 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -905,10 +905,13 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, switch (num) { case 0: - /* reset colors back to default */ + /* reset colors and attributes back to default */ fg = theme->default_color; bg = -1; - flags &= ~(GUI_PRINT_FLAG_COLOR_24_FG | GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_INDENT); + flags &= ~(GUI_PRINT_FLAG_INDENT | + GUI_PRINT_FLAG_BOLD | GUI_PRINT_FLAG_ITALIC | GUI_PRINT_FLAG_UNDERLINE | + GUI_PRINT_FLAG_BLINK | GUI_PRINT_FLAG_REVERSE | + GUI_PRINT_FLAG_COLOR_24_FG | GUI_PRINT_FLAG_COLOR_24_BG); break; case 1: /* hilight */ From f285332c5bb98c22952779f6d13664d3b2e3b847 Mon Sep 17 00:00:00 2001 From: Veres Lajos Date: Sat, 8 Nov 2014 22:26:53 +0000 Subject: [PATCH 0042/1650] typo fixes - https://github.com/vlajos/misspell_fixer --- NEWS | 8 ++++---- docs/help/in/echo.in | 4 ++-- docs/perl.txt | 4 ++-- docs/startup-HOWTO.html | 2 +- m4/glib-2.0.m4 | 2 +- src/core/commands.h | 2 +- src/core/net-nonblock.h | 2 +- src/core/net-sendbuffer.c | 2 +- src/core/net-sendbuffer.h | 2 +- src/core/network.c | 2 +- src/core/nicklist.c | 2 +- src/core/query-rec.h | 2 +- src/fe-text/tparm.c | 12 ++++++------ src/irc/core/channels-query.c | 2 +- src/irc/core/servers-redirect.c | 4 ++-- 15 files changed, 26 insertions(+), 26 deletions(-) diff --git a/NEWS b/NEWS index de36d195..fe6e5e58 100644 --- a/NEWS +++ b/NEWS @@ -368,7 +368,7 @@ v0.8.10 2005-12-11 The Irssi team can be almost everything listed by 'iconv -l' + Added transpose_words, capitalize_word, downcase_word, upcase_word key bindings - + Avoid accidentaly /VER in a channel, by requiring parameter + + Avoid accidentally /VER in a channel, by requiring parameter - Pasted lines weren't added to command history. Some other paste detection fixes - Fixed /BIND escape_char @@ -1905,7 +1905,7 @@ v0.7.14 1999-08-22 Timo Sirainen [unstable] - /msg completion was a bit buggy, if someone sent you multiple messages, you had to press tab multiple times until the nick changed to someone else.. - - Defaut format for signon time in whois displayed nick instead of + - Default format for signon time in whois displayed nick instead of the signon time.. - Disconnecting server while it was still trying to connect hung irssi - If old configuration file wasn't found, irssi (could have?) crashed @@ -2189,7 +2189,7 @@ v0.7.9 1999-04-22 Timo Sirainen [unstable] that matched the parameters - Commented out all GUI_INPUT_EXCEPTIONs .. I don't even know when exceptions are sent and why (I thought that only when some error - occured..), Linux doesn't seem to send them ever? IRIX however sends + occurred..), Linux doesn't seem to send them ever? IRIX however sends them all the time which made irssi eating all cpu. - Fixed compiling gui-text with systems that had only slang/slang.h - gui_widget_depends() had some bugs @@ -2635,7 +2635,7 @@ v0.3.2 1999-01-22 Timo Sirainen [unstable] v0.3.1 1999-01-22 Timo Sirainen - * 4 days since last relase. too long :) I'm now starting to create + * 4 days since last release. too long :) I'm now starting to create "unstable" versions of irssi. They have the latest and greatest features while they might not build/work too well. Check http://www.sicom.fi/~ikioma/irssi-download.html, new versions will diff --git a/docs/help/in/echo.in b/docs/help/in/echo.in index a730e282..4ff23730 100644 --- a/docs/help/in/echo.in +++ b/docs/help/in/echo.in @@ -6,10 +6,10 @@ %9Parameters:%9 -current: Displays the output in the active window. - -window: Displays the ouput in the target window. + -window: Displays the output in the target window. -level: Displays the output with a given message level. - The text ouput; if no target is given, the active window will be used. + The text output; if no target is given, the active window will be used. %9Description:%9 diff --git a/docs/perl.txt b/docs/perl.txt index 732b73af..79ab5820 100644 --- a/docs/perl.txt +++ b/docs/perl.txt @@ -796,7 +796,7 @@ Query->{} address - Host address of the queries nick server_tag - Server tag used for this nick (doesn't get erased if server gets disconnected) - unwanted - 1 if the other side closed or some error occured (DCC chats) + unwanted - 1 if the other side closed or some error occurred (DCC chats) Query query_create(chat_type, server_tag, nick, automatic) @@ -1123,7 +1123,7 @@ Netsplit->{} Netsplitserver->{} server - The server nick was in - destserver - The other server where split occured. + destserver - The other server where split occurred. count - Number of splits in server Netsplitchannel->{} diff --git a/docs/startup-HOWTO.html b/docs/startup-HOWTO.html index 736f25e9..30caf657 100644 --- a/docs/startup-HOWTO.html +++ b/docs/startup-HOWTO.html @@ -493,7 +493,7 @@ scrollback buffer. Simplest usages are

 /LASTLOG word     - print all lines with "word" in them
-/LASTLOG word 10  - print last 10 occurances of "word"
+/LASTLOG word 10  - print last 10 occurrences of "word"
 /LASTLOG -topics  - print all topic changes
 
diff --git a/m4/glib-2.0.m4 b/m4/glib-2.0.m4 index 2a5afd0c..2c8760b7 100644 --- a/m4/glib-2.0.m4 +++ b/m4/glib-2.0.m4 @@ -187,7 +187,7 @@ main () echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means GLIB is incorrectly installed."]) + echo "*** exact error that occurred. This usually means GLIB is incorrectly installed."]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi diff --git a/src/core/commands.h b/src/core/commands.h index c68c5b24..d65185e5 100644 --- a/src/core/commands.h +++ b/src/core/commands.h @@ -158,7 +158,7 @@ char *cmd_get_quoted_param(char **data); /* get parameters from command - you should point free_me somewhere and cmd_params_free() it after you don't use any of the parameters anymore. - Returns TRUE if all ok, FALSE if error occured. */ + Returns TRUE if all ok, FALSE if error occurred. */ int cmd_get_params(const char *data, gpointer *free_me, int count, ...); void cmd_params_free(void *free_me); diff --git a/src/core/net-nonblock.h b/src/core/net-nonblock.h index 32cfac70..af5968c8 100644 --- a/src/core/net-nonblock.h +++ b/src/core/net-nonblock.h @@ -29,7 +29,7 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int reverse_lookup); /* Get host's name, call func when finished */ int net_gethostbyaddr_nonblock(IPADDR *ip, NET_HOST_CALLBACK func, void *data); -/* get the resolved IP address. returns -1 if some error occured with read() */ +/* get the resolved IP address. returns -1 if some error occurred with read() */ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec); /* Connect to server, call func when finished */ diff --git a/src/core/net-sendbuffer.c b/src/core/net-sendbuffer.c index 9d4b0e37..39257486 100644 --- a/src/core/net-sendbuffer.c +++ b/src/core/net-sendbuffer.c @@ -109,7 +109,7 @@ static int buffer_add(NET_SENDBUF_REC *rec, const void *data, int size) /* Send data, if all of it couldn't be sent immediately, it will be resent automatically after a while. Returns -1 if some unrecoverable error - occured. */ + occurred. */ int net_sendbuffer_send(NET_SENDBUF_REC *rec, const void *data, int size) { int ret; diff --git a/src/core/net-sendbuffer.h b/src/core/net-sendbuffer.h index 785f59ae..bdeb7156 100644 --- a/src/core/net-sendbuffer.h +++ b/src/core/net-sendbuffer.h @@ -24,7 +24,7 @@ void net_sendbuffer_destroy(NET_SENDBUF_REC *rec, int close); /* Send data, if all of it couldn't be sent immediately, it will be resent automatically after a while. Returns -1 if some unrecoverable error - occured. */ + occurred. */ int net_sendbuffer_send(NET_SENDBUF_REC *rec, const void *data, int size); int net_sendbuffer_receive_line(NET_SENDBUF_REC *rec, char **str, int read_socket); diff --git a/src/core/network.c b/src/core/network.c index 3659ab36..bfaa47fb 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -624,7 +624,7 @@ const char *net_gethosterror(int error) int net_hosterror_notfound(int error) { #ifdef HAVE_IPV6 -#ifdef EAI_NODATA /* NODATA is depricated */ +#ifdef EAI_NODATA /* NODATA is deprecated */ return error != 1 && (error == EAI_NONAME || error == EAI_NODATA); #else return error != 1 && (error == EAI_NONAME); diff --git a/src/core/nicklist.c b/src/core/nicklist.c index a5f25f34..b1c9ecef 100644 --- a/src/core/nicklist.c +++ b/src/core/nicklist.c @@ -342,7 +342,7 @@ GSList *nicklist_get_same_unique(SERVER_REC *server, void *id) return rec.list; } -/* nick record comparision for sort functions */ +/* nick record comparison for sort functions */ int nicklist_compare(NICK_REC *p1, NICK_REC *p2, const char *nick_prefix) { int i; diff --git a/src/core/query-rec.h b/src/core/query-rec.h index fc08d2ef..59519ad4 100644 --- a/src/core/query-rec.h +++ b/src/core/query-rec.h @@ -7,5 +7,5 @@ char *server_tag; time_t last_unread_msg; unsigned int unwanted:1; /* TRUE if the other side closed or - some error occured (DCC chats!) */ + some error occurred (DCC chats!) */ unsigned int destroying:1; diff --git a/src/fe-text/tparm.c b/src/fe-text/tparm.c index 3f58e6f3..97c790da 100644 --- a/src/fe-text/tparm.c +++ b/src/fe-text/tparm.c @@ -153,7 +153,7 @@ static int termcap; 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 wether or not somthing has been pushed on the stack. + 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 @@ -170,7 +170,7 @@ static int termcap; %c output pop as a char %'c' push character constant c. %{n} push decimal constant n. - %p[1-9] push paramter [1-9] + %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) @@ -188,7 +188,7 @@ static int termcap; %O logical or pop and pop and push the result %! push the logical not of pop %? condition %t if_true [%e if_false] %; - if condtion evaulates as true then evaluate if_true, + 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) @@ -208,7 +208,7 @@ static int termcap; (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*(paramter%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 @@ -216,7 +216,7 @@ static int termcap; (GNU) %b backup to previous parameter (GNU) %f skip this parameter - Note the two definitions of %a, the GNU defintion is used if the characters + 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 @@ -316,7 +316,7 @@ char *tparm(const char *str, ...) { if ((sp[1] == 'p' || sp[1] == 'c') && sp[2] != '\0' && fmt == NULL) { /* GNU aritmitic parameter, what they - realy need is terminfo. */ + really need is terminfo. */ int val, lc; if (sp[1] == 'p' && getarg(termcap - 1 + sp[2] - '@', diff --git a/src/irc/core/channels-query.c b/src/irc/core/channels-query.c index 48ba5703..857ebaf0 100644 --- a/src/irc/core/channels-query.c +++ b/src/irc/core/channels-query.c @@ -311,7 +311,7 @@ static void channel_checksync(IRC_CHANNEL_REC *channel) signal_emit("channel sync", 1, channel); } -/* Error occured when trying to execute query - abort and try again. */ +/* Error occurred when trying to execute query - abort and try again. */ static void query_current_error(IRC_SERVER_REC *server) { SERVER_QUERY_REC *rec; diff --git a/src/irc/core/servers-redirect.c b/src/irc/core/servers-redirect.c index 34beaef6..518248cb 100644 --- a/src/irc/core/servers-redirect.c +++ b/src/irc/core/servers-redirect.c @@ -734,7 +734,7 @@ void servers_redirect_init(void) "event 403", 1, /* no such channel */ "event 442", 1, /* "you're not on that channel" */ "event 479", 1, /* "Cannot join channel (illegal name)" IMHO this is not a logical reply from server. */ - "event 472", -1, /* unknown mode (you should check e-mode's existance from 004 event instead of relying on this) */ + "event 472", -1, /* unknown mode (you should check e-mode's existence from 004 event instead of relying on this) */ NULL, NULL); @@ -747,7 +747,7 @@ void servers_redirect_init(void) "event 403", 1, /* no such channel */ "event 442", 1, /* "you're not on that channel" */ "event 479", 1, /* "Cannot join channel (illegal name)" IMHO this is not a logical reply from server. */ - "event 472", -1, /* unknown mode (you should check I-mode's existance from 004 event instead of relying on this) */ + "event 472", -1, /* unknown mode (you should check I-mode's existence from 004 event instead of relying on this) */ NULL, NULL); From b03805eeb916712815971ac6bcfffe10cc16711f Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Tue, 4 Nov 2014 12:08:27 +0100 Subject: [PATCH 0043/1650] reimplement format and length logic for the entry prompt --- src/fe-common/core/printtext.c | 12 ++++++++++++ src/fe-common/core/printtext.h | 1 + src/fe-text/gui-entry.c | 32 ++++++++++++++++++++++++++++++-- src/fe-text/gui-printtext.c | 10 ++++++++++ src/fe-text/gui-printtext.h | 1 + 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/fe-common/core/printtext.c b/src/fe-common/core/printtext.c index 466a2825..ba6f3242 100644 --- a/src/fe-common/core/printtext.c +++ b/src/fe-common/core/printtext.c @@ -413,6 +413,18 @@ void printtext_gui(const char *text) g_free(str); } +/* Like printtext_gui(), but don't expand % codes. */ +void printtext_gui_internal(const char *str) +{ + TEXT_DEST_REC dest; + + g_return_if_fail(str != NULL); + + memset(&dest, 0, sizeof(dest)); + + format_send_to_gui(&dest, str); +} + static void msg_beep_check(TEXT_DEST_REC *dest) { if (dest->level != 0 && (dest->level & MSGLEVEL_NO_ACT) == 0 && diff --git a/src/fe-common/core/printtext.h b/src/fe-common/core/printtext.h index 66ba28f4..ab8dfac1 100644 --- a/src/fe-common/core/printtext.h +++ b/src/fe-common/core/printtext.h @@ -23,6 +23,7 @@ void printtext_dest(TEXT_DEST_REC *dest, const char *text, ...); /* only GUI should call these - used for printing text to somewhere else than windows */ void printtext_gui(const char *text); +void printtext_gui_internal(const char *str); void printformat_module_gui(const char *module, int formatnum, ...); void printformat_module_gui_args(const char *module, int formatnum, va_list va); diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 17a7c507..309f3a68 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -26,6 +26,7 @@ #include "gui-entry.h" #include "gui-printtext.h" #include "term.h" +#include "recode.h" #undef i_toupper #undef i_tolower @@ -345,6 +346,33 @@ void gui_entry_set_active(GUI_ENTRY_REC *entry) } } +/* Return screen length of plain string */ +static int scrlen_str(const char *str) +{ + int len = 0; + char *stripped; + g_return_val_if_fail(str != NULL, 0); + + str = stripped = strip_codes(str); + if (is_utf8() && g_utf8_validate(str, -1, NULL)) { + + 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); + } + + g_free(stripped); + return len; +} + void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const char *str) { int oldlen; @@ -355,11 +383,11 @@ void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const char *str) if (str != NULL) { g_free_not_null(entry->prompt); entry->prompt = g_strdup(str); - entry->promptlen = format_get_length(str); + entry->promptlen = scrlen_str(str); } if (entry->prompt != NULL) - gui_printtext(entry->xpos, entry->ypos, entry->prompt); + gui_printtext_internal(entry->xpos, entry->ypos, entry->prompt); if (entry->promptlen != oldlen) { gui_entry_fix_cursor(entry); diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c index 547d39c9..83b26e82 100644 --- a/src/fe-text/gui-printtext.c +++ b/src/fe-text/gui-printtext.c @@ -109,6 +109,16 @@ void gui_printtext(int xpos, int ypos, const char *str) next_xpos = next_ypos = -1; } +void gui_printtext_internal(int xpos, int ypos, const char *str) +{ + next_xpos = xpos; + next_ypos = ypos; + + printtext_gui_internal(str); + + next_xpos = next_ypos = -1; +} + void gui_printtext_after_time(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str, time_t time) { GUI_WINDOW_REC *gui; diff --git a/src/fe-text/gui-printtext.h b/src/fe-text/gui-printtext.h index 33b7ce6f..d2671497 100644 --- a/src/fe-text/gui-printtext.h +++ b/src/fe-text/gui-printtext.h @@ -17,6 +17,7 @@ void gui_set_default_indent(const char *name); INDENT_FUNC get_default_indent_func(void); void gui_printtext(int xpos, int ypos, const char *str); +void gui_printtext_internal(int xpos, int ypos, const char *str); void gui_printtext_after(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str); void gui_printtext_after_time(TEXT_DEST_REC *dest, LINE_REC *prev, const char *str, time_t time); From 0bba34bbe9b3510ae71cfb83e686de3d3cfb9376 Mon Sep 17 00:00:00 2001 From: dequis Date: Fri, 14 Nov 2014 03:46:02 -0300 Subject: [PATCH 0044/1650] Fix -ssl_pass documentation in /server and /connect Copied text from 68f8229 (SVN r5231) --- docs/help/in/connect.in | 1 + docs/help/in/server.in | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/help/in/connect.in b/docs/help/in/connect.in index 1c1aa2bb..3330966e 100644 --- a/docs/help/in/connect.in +++ b/docs/help/in/connect.in @@ -11,6 +11,7 @@ -ssl_cert: The SSL client certificate file. -ssl_pkey: The SSL client private key, if not included in the certificate file. + -ssl_pass: The password for the SSL client private key or certificate. -ssl_verify: Verifies the SSL certificate of the server. -ssl_cafile: The file with the list of CA certificates. -ssl_capath: The directory which contains the CA certificates. diff --git a/docs/help/in/server.in b/docs/help/in/server.in index d8bcb9a7..f6706daf 100644 --- a/docs/help/in/server.in +++ b/docs/help/in/server.in @@ -18,7 +18,7 @@ -ssl_cert: The SSL client certificate file. -ssl_pkey: The SSL client private key, if not included in the certificate file. - -ssl_pass: Verifies the SSL certificate of the server. + -ssl_pass: The password for the SSL client private key or certificate. -ssl_verify: Verifies the SSL certificate of the server. -ssl_cafile: The file with the list of CA certificates. -ssl_capath: The directory which contains the CA certificates. From f0a6e5f82a909b5789dfdfa4928ad3d8c4b078a3 Mon Sep 17 00:00:00 2001 From: Guillaume BROGI Date: Thu, 20 Nov 2014 17:01:07 +0100 Subject: [PATCH 0045/1650] Correctly parse unix sockets servers in the config --- src/core/servers-setup.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 0819ff1a..27d9f1f0 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -122,6 +122,9 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn, conn->address = g_strdup(address); if (port > 0) conn->port = port; + if (strchr(address, '/') != NULL) + conn->unix_socket = TRUE; + if (!conn->nick) conn->nick = g_strdup(settings_get_str("nick")); conn->username = g_strdup(settings_get_str("user_name")); conn->realname = g_strdup(settings_get_str("real_name")); From 86d263dd7dd39bbb768284fb6b586d1979a821cd Mon Sep 17 00:00:00 2001 From: Guillaume BROGI Date: Wed, 3 Dec 2014 09:43:24 +0100 Subject: [PATCH 0046/1650] Check for unix sockets when reconnecting --- src/core/servers-reconnect.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index 0a08b461..d99a5405 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -253,6 +253,9 @@ static void sig_reconnect(SERVER_REC *server) conn->port = server->connrec->port; conn->password = g_strdup(server->connrec->password); + if (strchr(conn->address, '/') != NULL) + conn->unix_socket = TRUE; + server_reconnect_add(conn, (server->connect_time == 0 ? time(NULL) : server->connect_time) + reconnect_time); server_connect_unref(conn); From 08b390b11b327f33f77a79816409b595775d4194 Mon Sep 17 00:00:00 2001 From: Geert Hauwaerts Date: Mon, 8 Dec 2014 21:28:02 +0100 Subject: [PATCH 0047/1650] Documentation fix for #185 Documentation fix for #185 --- docs/help/in/disconnect.in | 7 ++++--- docs/help/in/msg.in | 4 ++++ src/core/chat-commands.c | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/help/in/disconnect.in b/docs/help/in/disconnect.in index ace1a3df..bd4a4e17 100644 --- a/docs/help/in/disconnect.in +++ b/docs/help/in/disconnect.in @@ -10,10 +10,11 @@ %9Description:%9 - Disconnects from one or more IRC servers; the list of all the servers you - are connected to can be retrieved via the SERVER command. + Disconnects from an IRC server; the list of all the servers you are + connected to can be retrieved via the SERVER command. - Use the wildcard character '*' if you want to disconnect from all servers. + Use the wildcard character '*' if you want to disconnect from the active + server. %9Examples:%9 diff --git a/docs/help/in/msg.in b/docs/help/in/msg.in index dc70f1f3..9e0879e4 100644 --- a/docs/help/in/msg.in +++ b/docs/help/in/msg.in @@ -11,6 +11,9 @@ The target nickname or channel and the message to send. + Use the wildcard character '*' if you want to use the active nickname or + channel. + %9Description:%9 Sends a message to a nickname or channel. @@ -19,6 +22,7 @@ /MSG mike Hi, what's up? /MSG #irssi I am awesome :) + /MSG * Do you want to build a snowman? %9See also:%9 ACTION, DCC, JOIN diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 235a9fc4..8d1ac3eb 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -321,7 +321,7 @@ static void cmd_quit(const char *data) signal_emit("gui exit", 0); } -/* SYNTAX: MSG [-] [-channel | -nick] */ +/* SYNTAX: MSG [-] [-channel | -nick] *| */ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; From 367d8efc5ffca32ce6a6407fddb5253ed9eab1a4 Mon Sep 17 00:00:00 2001 From: dequis Date: Sun, 14 Dec 2014 18:21:40 -0300 Subject: [PATCH 0048/1650] Fix blinking/bold text in terminals with no color support Before this, doing "TERM=vt100 irssi" showed all text as bold and blinking because of a failed check of window->term->TI_colors that was doing (value & 8) and not expecting a value of 0. The changed lines themselves look a bit weird, but they make more sense in the context of the original commit, 96a292d4. --- src/fe-text/term-terminfo.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c index 29d3f7eb..ded79c28 100644 --- a/src/fe-text/term-terminfo.c +++ b/src/fe-text/term-terminfo.c @@ -390,7 +390,8 @@ void term_set_color(TERM_WINDOW *window, int col) } /* set background color */ - if (window && (term_color256map[bg&0xff]&8) == window->term->TI_colors) + if (window && window->term->TI_colors && + (term_color256map[bg&0xff]&8) == window->term->TI_colors) col |= ATTR_BLINK; if (col & ATTR_BLINK) current_term->set_blink(current_term); @@ -413,7 +414,8 @@ void term_set_color(TERM_WINDOW *window, int col) terminfo_set_reverse(); /* bold */ - if (window && (term_color256map[fg&0xff]&8) == window->term->TI_colors) + if (window && window->term->TI_colors && + (term_color256map[fg&0xff]&8) == window->term->TI_colors) col |= ATTR_BOLD; if (col & ATTR_BOLD) terminfo_set_bold(); From db62ddfd557799981d779914a5e82473a6b22df8 Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Tue, 16 Dec 2014 12:14:23 +0000 Subject: [PATCH 0049/1650] Die if the wrong type of node is found when traversing config Fixes issue #187. It's a bit annoying this can't do anything other than exit, however as there's no schema for the config it's only possible to validate on use. This level of config can't be accessed from Perl so a script can't cause Irssi to die (via this method at least). --- src/lib-config/get.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib-config/get.c b/src/lib-config/get.c index 2f1e90e1..af02b048 100644 --- a/src/lib-config/get.c +++ b/src/lib-config/get.c @@ -109,6 +109,12 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea } g_strfreev(list); + if (!is_node_list(node)) { + /* Will die. Better to not corrupt the config further in this case. */ + g_error("Attempt to use non-list node as list. Corrupt config?"); + return NULL; + } + /* save to cache */ str = g_strdup(section); g_hash_table_insert(rec->cache, str, node); From dfc65d959e474d1235f894dc3b5631cb7ad48c2c Mon Sep 17 00:00:00 2001 From: "Nico R. Wohlgemuth" Date: Tue, 13 Jan 2015 18:44:16 +0100 Subject: [PATCH 0050/1650] Remove splitlong.pl, it is enabled natively (#1) --- scripts/Makefile.am | 1 - scripts/splitlong.pl | 60 -------------------------------------------- 2 files changed, 61 deletions(-) delete mode 100644 scripts/splitlong.pl diff --git a/scripts/Makefile.am b/scripts/Makefile.am index b3c641b7..23eb7198 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -13,7 +13,6 @@ script_DATA = \ quitmsg.pl \ sb_search.pl \ scriptassist.pl \ - splitlong.pl \ usercount.pl EXTRA_DIST = $(script_DATA) diff --git a/scripts/splitlong.pl b/scripts/splitlong.pl deleted file mode 100644 index e88840bc..00000000 --- a/scripts/splitlong.pl +++ /dev/null @@ -1,60 +0,0 @@ -# /set splitlong_max_length -# specifies the maximum length of a msg, automatically chosen when set to "0" -# default: 0 -# -# /set splitlong_line_start -# /set splitlong_line_end -# self-explanatory -# defaults: "... ", " ..." -### -use strict; -use vars qw($VERSION %IRSSI); - -use Irssi 20011001; - -$VERSION = "0.20"; -%IRSSI = ( - authors => "Bjoern \'fuchs\' Krombholz", - contact => "bjkro\@gmx.de", - name => "splitlong", - licence => "Public Domain", - description => "Split overlong PRIVMSGs to msgs with length allowed by ircd", - changed => "Wed Jun 25 00:17:00 CET 2003", - changes => "Actually the real 0.19 (now 0.20), but upload didn't work some month ago, target problem fixed..." -); - -sub sig_command_msg { - my ($cmd, $server, $winitem) = @_; - my ( $param, $target,$data) = $cmd =~ /^(-\S*\s)?(\S*)\s(.*)/; - - my $maxlength = Irssi::settings_get_int('splitlong_max_length'); - my $lstart = Irssi::settings_get_str('splitlong_line_start'); - my $lend = Irssi::settings_get_str('splitlong_line_end'); - - if ($maxlength == 0) { - # 497 = 510 - length(":" . "!" . " PRIVMSG " . " :"); - $maxlength = 497 - length($server->{nick} . $server->{userhost} . $target); - } - my $maxlength2 = $maxlength - length($lend); - - if (length($data) > ($maxlength)) { - my @spltarr; - - while (length($data) > ($maxlength2)) { - my $pos = rindex($data, " ", $maxlength2); - push @spltarr, substr($data, 0, ($pos < ($maxlength/10 + 4)) ? $maxlength2 : $pos) . $lend; - $data = $lstart . substr($data, ($pos < ($maxlength/10 + 4)) ? $maxlength2 : $pos+1); - } - - push @spltarr, $data; - foreach (@spltarr) { - Irssi::signal_emit("command msg", "$target $_", $server, $winitem); - } - Irssi::signal_stop(); - } -} - -Irssi::settings_add_int('misc', 'splitlong_max_length', 0); -Irssi::settings_add_str('misc', 'splitlong_line_start', "... "); -Irssi::settings_add_str('misc', 'splitlong_line_end', " ..."); -Irssi::command_bind('msg', 'sig_command_msg'); From 4bf9e1f16aa1d41407ece0d61148907eae666783 Mon Sep 17 00:00:00 2001 From: KindOne Date: Sat, 17 Jan 2015 08:11:10 -0500 Subject: [PATCH 0051/1650] Do not let the ctcp action of an inital query go into the status window. --- src/fe-common/irc/fe-irc-messages.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index e0849c75..314f4f53 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -179,7 +179,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, item = irc_channel_find(server, target); } else { own = (!strcmp(nick, server->nick)); - item = privmsg_get_query(SERVER(server), own ? nick : target, FALSE, level); + item = privmsg_get_query(SERVER(server), own ? target : nick, FALSE, level); } if (settings_get_bool("emphasis")) From 7ca9c86445daff6232f8b876b27e7d10f9d5be5c Mon Sep 17 00:00:00 2001 From: dequis Date: Sat, 31 Jan 2015 11:49:01 -0300 Subject: [PATCH 0052/1650] /help lastlog: Clarify usage of - parameter --- docs/help/in/lastlog.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/help/in/lastlog.in b/docs/help/in/lastlog.in index e7b90d42..bb3a6fee 100644 --- a/docs/help/in/lastlog.in +++ b/docs/help/in/lastlog.in @@ -10,7 +10,7 @@ -window: Specifies the window to check. -new: Only displays results since the previous lastlog. -away: Only displays results since you previous away status. - -level: Specifies the levels to check. + -: Specifies the levels to check (e.g. -joins -quits -hilight) -clear: Removes the previous results from the active window. -count: Displays how many lines match. -case: Performs a case-sensitive matching. @@ -32,6 +32,7 @@ /LASTLOG holiday /LASTLOG 'is on vacation' /LASTLOG -file -force ~/mike.log 'mike' + /LASTLOG -hilight %9See also:%9 HILIGHT, SCROLLBACK From a26a909af0cd7e75af4b7fa5a209301455a33c36 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Sun, 1 Feb 2015 19:21:59 +0100 Subject: [PATCH 0053/1650] Fix the lastlog help Correct some confusing inaccuracies and document a parameters that got lost on the rewrite. --- docs/help/in/lastlog.in | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/help/in/lastlog.in b/docs/help/in/lastlog.in index bb3a6fee..3815f5d2 100644 --- a/docs/help/in/lastlog.in +++ b/docs/help/in/lastlog.in @@ -17,8 +17,11 @@ -regexp: The given text pattern is a regular expression. -word: The text must match full words. -force: Forces to display the lastlog, even if it exceeds 1000 lines. - -after: Only displays results after the given line number. - -before: Only displays results before the given line number. + -after: Include this many lines of content after the match. + -before: Include this many lines of content before the match. + -<#>: Include this many lines of content around the match. + : Display a maximum number of `count' lines. + : Skip the last `start' lines. The pattern to search for and the maximum of lines to display; if no parameter is given, the entire window buffer will be displayed. @@ -30,9 +33,10 @@ %9Examples:%9 /LASTLOG holiday - /LASTLOG 'is on vacation' + /LASTLOG 'is on vacation' 10 /LASTLOG -file -force ~/mike.log 'mike' /LASTLOG -hilight + /LASTLOG -5 searchterm %9See also:%9 HILIGHT, SCROLLBACK From 378cab29f42beb75b6168afdc342ce1b2c21fcdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Mart=C3=ADn=20B=C3=A1ez=20Echevarr=C3=ADa?= Date: Sun, 1 Feb 2015 20:24:05 -0200 Subject: [PATCH 0054/1650] Fix comment in default.theme: msgownnick -> ownnick --- default.theme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.theme b/default.theme index ac99356a..6b6aeab8 100644 --- a/default.theme +++ b/default.theme @@ -120,7 +120,7 @@ abstracts = { # the basic styling of how to print message, $0 = nick mode, $1 = nick msgnick = "%K<%n$0$1-%K>%n %|"; - # message from you is printed. "msgownnick" specifies the styling of the + # message from you is printed. "ownnick" specifies the styling of the # nick ($0 part in msgnick) and "ownmsgnick" specifies the styling of the # whole line. From 466166010b751efc622af444e00c33a843c98063 Mon Sep 17 00:00:00 2001 From: Vesa Pirila Date: Sun, 8 Feb 2015 12:39:23 +0200 Subject: [PATCH 0055/1650] Added a -date parameter to /lastlog to prepend each row with the row's date --- docs/help/in/lastlog.in | 1 + src/fe-text/lastlog.c | 23 ++++++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/docs/help/in/lastlog.in b/docs/help/in/lastlog.in index 3815f5d2..e6f5886a 100644 --- a/docs/help/in/lastlog.in +++ b/docs/help/in/lastlog.in @@ -14,6 +14,7 @@ -clear: Removes the previous results from the active window. -count: Displays how many lines match. -case: Performs a case-sensitive matching. + -date: Prepends each row with the message's date (YYYY-MM-DD). -regexp: The given text pattern is a regular expression. -word: The text must match full words. -force: Forces to display the lastlog, even if it exceeds 1000 lines. diff --git a/src/fe-text/lastlog.c b/src/fe-text/lastlog.c index 417eb484..fe3cf5af 100644 --- a/src/fe-text/lastlog.c +++ b/src/fe-text/lastlog.c @@ -74,6 +74,17 @@ int cmd_options_get_level(const char *cmd, GHashTable *optlist) return retlevel; } +static void prepend_date(LINE_REC *rec, GString *line) +{ + struct tm *tm = localtime(&rec->info.time); + char timestamp[12]; + + g_snprintf(timestamp, sizeof(timestamp), + "%04d-%02d-%02d ", + tm->tm_year+1900, tm->tm_mon, tm->tm_mday); + g_string_prepend(line, timestamp); +} + static void show_lastlog(const char *searchtext, GHashTable *optlist, int start, int count, FILE *fhandle) { @@ -82,7 +93,7 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist, GList *list, *tmp; GString *line; char *str; - int level, before, after, len; + int level, before, after, len, date = FALSE; level = cmd_options_get_level("lastlog", optlist); if (level == -1) return; /* error in options */ @@ -132,6 +143,9 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist, atoi(str) : DEFAULT_LASTLOG_AFTER; } + if (g_hash_table_lookup(optlist, "date") != NULL) + date = TRUE; + list = textbuffer_find_text(WINDOW_GUI(window)->view->buffer, startline, level, MSGLEVEL_LASTLOG, searchtext, before, after, @@ -199,6 +213,9 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist, g_string_prepend(line, timestamp); } + if (date == TRUE) + prepend_date(rec, line); + /* write to file/window */ if (fhandle != NULL) { fwrite(line->str, line->len, 1, fhandle); @@ -223,7 +240,7 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist, } /* SYNTAX: LASTLOG [-] [-file ] [-window ] [-new | -away] - [- -] [-clear] [-count] [-case] + [- -] [-clear] [-count] [-case] [-date] [-regexp | -word] [-before [<#>]] [-after [<#>]] [-<# before+after>] [] [ []] */ static void cmd_lastlog(const char *data) @@ -285,7 +302,7 @@ void lastlog_init(void) { command_bind("lastlog", NULL, (SIGNAL_FUNC) cmd_lastlog); - command_set_options("lastlog", "!- # force clear -file -window new away word regexp case count @a @after @before"); + command_set_options("lastlog", "!- # force clear -file -window new away word regexp case count date @a @after @before"); } void lastlog_deinit(void) From cd5a571fd8aba12b6b8ddbf54e947ac4cc1e516e Mon Sep 17 00:00:00 2001 From: Vesa Pirila Date: Sun, 8 Feb 2015 16:58:30 +0200 Subject: [PATCH 0056/1650] Added customization possibility for the lastlog date format, lastlog_date --- docs/help/in/lastlog.in | 2 +- src/fe-text/lastlog.c | 22 +++++++++++++++------- src/fe-text/module-formats.c | 1 + src/fe-text/module-formats.h | 1 + 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/help/in/lastlog.in b/docs/help/in/lastlog.in index e6f5886a..25879d31 100644 --- a/docs/help/in/lastlog.in +++ b/docs/help/in/lastlog.in @@ -14,7 +14,7 @@ -clear: Removes the previous results from the active window. -count: Displays how many lines match. -case: Performs a case-sensitive matching. - -date: Prepends each row with the message's date (YYYY-MM-DD). + -date: Prepends each row with the message's date -regexp: The given text pattern is a regular expression. -word: The text must match full words. -force: Forces to display the lastlog, even if it exceeds 1000 lines. diff --git a/src/fe-text/lastlog.c b/src/fe-text/lastlog.c index fe3cf5af..3c700d76 100644 --- a/src/fe-text/lastlog.c +++ b/src/fe-text/lastlog.c @@ -74,15 +74,23 @@ int cmd_options_get_level(const char *cmd, GHashTable *optlist) return retlevel; } -static void prepend_date(LINE_REC *rec, GString *line) +static void prepend_date(WINDOW_REC *window, LINE_REC *rec, GString *line) { + THEME_REC *theme = NULL; + TEXT_DEST_REC dest = {0}; + char *format = NULL, datestamp[20] = {0}; struct tm *tm = localtime(&rec->info.time); - char timestamp[12]; + int ret = 0; - g_snprintf(timestamp, sizeof(timestamp), - "%04d-%02d-%02d ", - tm->tm_year+1900, tm->tm_mon, tm->tm_mday); - g_string_prepend(line, timestamp); + theme = window->theme != NULL ? window->theme : current_theme; + format_create_dest(&dest, NULL, NULL, MSGLEVEL_LASTLOG, window); + format = format_get_text_theme(theme, MODULE_NAME, &dest, TXT_LASTLOG_DATE); + + ret = strftime(datestamp, sizeof(datestamp), format, tm); + g_free(format); + if (ret <= 0) return; + + g_string_prepend(line, datestamp); } static void show_lastlog(const char *searchtext, GHashTable *optlist, @@ -214,7 +222,7 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist, } if (date == TRUE) - prepend_date(rec, line); + prepend_date(window, rec, line); /* write to file/window */ if (fhandle != NULL) { diff --git a/src/fe-text/module-formats.c b/src/fe-text/module-formats.c index 1d905095..899827c2 100644 --- a/src/fe-text/module-formats.c +++ b/src/fe-text/module-formats.c @@ -33,6 +33,7 @@ FORMAT_REC gui_text_formats[] = { "lastlog_start", "{hilight Lastlog}:", 0 }, { "lastlog_end", "{hilight End of Lastlog}", 0 }, { "lastlog_separator", "--", 0 }, + { "lastlog_date", "%%F ", 0 }, /* ---- */ { NULL, "Windows", 0 }, diff --git a/src/fe-text/module-formats.h b/src/fe-text/module-formats.h index 4eebfc3e..3fa8c511 100644 --- a/src/fe-text/module-formats.h +++ b/src/fe-text/module-formats.h @@ -10,6 +10,7 @@ enum { TXT_LASTLOG_START, TXT_LASTLOG_END, TXT_LASTLOG_SEPARATOR, + TXT_LASTLOG_DATE, TXT_FILL_2, From b4b4ebfadfb580b76e2a2aee301ae7a61dde775e Mon Sep 17 00:00:00 2001 From: mauke Date: Sun, 8 Feb 2015 22:16:01 +0100 Subject: [PATCH 0057/1650] accept freenode extbans in /ban [#150] --- src/irc/core/bans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/irc/core/bans.c b/src/irc/core/bans.c index d8d5d448..38c81aab 100644 --- a/src/irc/core/bans.c +++ b/src/irc/core/bans.c @@ -88,7 +88,7 @@ char *ban_get_masks(IRC_CHANNEL_REC *channel, const char *nicks, int ban_type) str = g_string_new(NULL); banlist = g_strsplit(nicks, " ", -1); for (ban = banlist; *ban != NULL; ban++) { - if (strchr(*ban, '!') != NULL) { + if (**ban == '$' || strchr(*ban, '!') != NULL) { /* explicit ban */ g_string_append_printf(str, "%s ", *ban); continue; From dee7825f05e0e558020fabe2e536e2b5d4df8050 Mon Sep 17 00:00:00 2001 From: Alexandre Morignot Date: Tue, 10 Feb 2015 16:37:41 +0100 Subject: [PATCH 0058/1650] handle an already used nick different from the one we send --- src/irc/core/irc-nicklist.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c index 5438509e..a006a3cb 100644 --- a/src/irc/core/irc-nicklist.c +++ b/src/irc/core/irc-nicklist.c @@ -343,7 +343,7 @@ static void event_nick_invalid(IRC_SERVER_REC *server, const char *data) static void event_nick_in_use(IRC_SERVER_REC *server, const char *data) { - char *str, *cmd; + char *str, *cmd, *params, *nick; int n; g_return_if_fail(data != NULL); @@ -353,6 +353,14 @@ static void event_nick_in_use(IRC_SERVER_REC *server, const char *data) return; } + params = event_get_params(data, 2, NULL, &nick); + if (g_ascii_strcasecmp(server->nick, nick) != 0) { + /* the server uses a nick different from the one we send */ + g_free(server->nick); + server->nick = g_strdup(nick); + } + g_free(params); + /* nick already in use - need to change it .. */ if (g_ascii_strcasecmp(server->nick, server->connrec->nick) == 0 && server->connrec->alternate_nick != NULL && From 895ac10c4eaa347cf2dbe184fc9480a8f47168ee Mon Sep 17 00:00:00 2001 From: Vesa Pirila Date: Mon, 16 Feb 2015 09:49:22 +0200 Subject: [PATCH 0059/1650] lastlog.c is a mix of tab and space indentation. My changes now use tabs. --- src/fe-text/lastlog.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/fe-text/lastlog.c b/src/fe-text/lastlog.c index 3c700d76..166d2847 100644 --- a/src/fe-text/lastlog.c +++ b/src/fe-text/lastlog.c @@ -76,19 +76,19 @@ int cmd_options_get_level(const char *cmd, GHashTable *optlist) static void prepend_date(WINDOW_REC *window, LINE_REC *rec, GString *line) { - THEME_REC *theme = NULL; - TEXT_DEST_REC dest = {0}; - char *format = NULL, datestamp[20] = {0}; + THEME_REC *theme = NULL; + TEXT_DEST_REC dest = {0}; + char *format = NULL, datestamp[20] = {0}; struct tm *tm = localtime(&rec->info.time); int ret = 0; - theme = window->theme != NULL ? window->theme : current_theme; - format_create_dest(&dest, NULL, NULL, MSGLEVEL_LASTLOG, window); - format = format_get_text_theme(theme, MODULE_NAME, &dest, TXT_LASTLOG_DATE); + theme = window->theme != NULL ? window->theme : current_theme; + format_create_dest(&dest, NULL, NULL, MSGLEVEL_LASTLOG, window); + format = format_get_text_theme(theme, MODULE_NAME, &dest, TXT_LASTLOG_DATE); ret = strftime(datestamp, sizeof(datestamp), format, tm); - g_free(format); - if (ret <= 0) return; + g_free(format); + if (ret <= 0) return; g_string_prepend(line, datestamp); } From 8e8bc5fdbc4894e87a195caee83c551a0e983275 Mon Sep 17 00:00:00 2001 From: dequis Date: Sat, 20 Dec 2014 19:46:12 -0300 Subject: [PATCH 0060/1650] Silence unused value warnings in perl binding code sed -i 's/hv_store/(void) &/' This only results in a warning in older gcc versions, but that includes the one used in the Travis CI environment by default --- src/perl/common/Core.xs | 2 +- src/perl/irc/Irc.xs | 128 +++++++++---------- src/perl/perl-common.c | 230 +++++++++++++++++------------------ src/perl/textui/Statusbar.xs | 4 +- src/perl/textui/TextUI.xs | 66 +++++----- src/perl/ui/UI.xs | 64 +++++----- 6 files changed, 247 insertions(+), 247 deletions(-) diff --git a/src/perl/common/Core.xs b/src/perl/common/Core.xs index bfe2efde..5d2f7bca 100644 --- a/src/perl/common/Core.xs +++ b/src/perl/common/Core.xs @@ -63,7 +63,7 @@ static void add_tuple(gpointer key_, gpointer value_, gpointer user_data) HV *hash = user_data; char *key = key_; char *value = value_; - hv_store(hash, key, strlen(key), new_pv(value), 0); + (void) hv_store(hash, key, strlen(key), new_pv(value), 0); } static void wrap_signal_emit(void *signal, void **p) { diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs index 22a87384..18665cb7 100644 --- a/src/perl/irc/Irc.xs +++ b/src/perl/irc/Irc.xs @@ -6,90 +6,90 @@ static int initialized = FALSE; static void perl_irc_connect_fill_hash(HV *hv, IRC_SERVER_CONNECT_REC *conn) { perl_connect_fill_hash(hv, (SERVER_CONNECT_REC *) conn); - hv_store(hv, "alternate_nick", 14, new_pv(conn->alternate_nick), 0); + (void) hv_store(hv, "alternate_nick", 14, new_pv(conn->alternate_nick), 0); } static void perl_irc_server_fill_hash(HV *hv, IRC_SERVER_REC *server) { perl_server_fill_hash(hv, (SERVER_REC *) server); - hv_store(hv, "real_address", 12, new_pv(server->real_address), 0); - hv_store(hv, "usermode", 8, new_pv(server->usermode), 0); - hv_store(hv, "userhost", 8, new_pv(server->userhost), 0); + (void) hv_store(hv, "real_address", 12, new_pv(server->real_address), 0); + (void) hv_store(hv, "usermode", 8, new_pv(server->usermode), 0); + (void) hv_store(hv, "userhost", 8, new_pv(server->userhost), 0); - hv_store(hv, "max_cmds_at_once", 16, newSViv(server->max_cmds_at_once), 0); - hv_store(hv, "cmd_queue_speed", 15, newSViv(server->cmd_queue_speed), 0); - hv_store(hv, "max_query_chans", 15, newSViv(server->max_query_chans), 0); + (void) hv_store(hv, "max_cmds_at_once", 16, newSViv(server->max_cmds_at_once), 0); + (void) hv_store(hv, "cmd_queue_speed", 15, newSViv(server->cmd_queue_speed), 0); + (void) hv_store(hv, "max_query_chans", 15, newSViv(server->max_query_chans), 0); - hv_store(hv, "max_kicks_in_cmd", 16, newSViv(server->max_kicks_in_cmd), 0); - hv_store(hv, "max_msgs_in_cmd", 15, newSViv(server->max_msgs_in_cmd), 0); - hv_store(hv, "max_modes_in_cmd", 16, newSViv(server->max_modes_in_cmd), 0); - hv_store(hv, "max_whois_in_cmd", 16, newSViv(server->max_whois_in_cmd), 0); - hv_store(hv, "isupport_sent", 13, newSViv(server->isupport_sent), 0); + (void) hv_store(hv, "max_kicks_in_cmd", 16, newSViv(server->max_kicks_in_cmd), 0); + (void) hv_store(hv, "max_msgs_in_cmd", 15, newSViv(server->max_msgs_in_cmd), 0); + (void) hv_store(hv, "max_modes_in_cmd", 16, newSViv(server->max_modes_in_cmd), 0); + (void) hv_store(hv, "max_whois_in_cmd", 16, newSViv(server->max_whois_in_cmd), 0); + (void) hv_store(hv, "isupport_sent", 13, newSViv(server->isupport_sent), 0); } static void perl_ban_fill_hash(HV *hv, BAN_REC *ban) { - hv_store(hv, "ban", 3, new_pv(ban->ban), 0); - hv_store(hv, "setby", 5, new_pv(ban->setby), 0); - hv_store(hv, "time", 4, newSViv(ban->time), 0); + (void) hv_store(hv, "ban", 3, new_pv(ban->ban), 0); + (void) hv_store(hv, "setby", 5, new_pv(ban->setby), 0); + (void) hv_store(hv, "time", 4, newSViv(ban->time), 0); } static void perl_dcc_fill_hash(HV *hv, DCC_REC *dcc) { - hv_store(hv, "type", 4, new_pv(dcc_type2str(dcc->type)), 0); - hv_store(hv, "orig_type", 9, new_pv(dcc_type2str(dcc->orig_type)), 0); - hv_store(hv, "created", 7, newSViv(dcc->created), 0); + (void) hv_store(hv, "type", 4, new_pv(dcc_type2str(dcc->type)), 0); + (void) hv_store(hv, "orig_type", 9, new_pv(dcc_type2str(dcc->orig_type)), 0); + (void) hv_store(hv, "created", 7, newSViv(dcc->created), 0); - hv_store(hv, "server", 6, iobject_bless(dcc->server), 0); - hv_store(hv, "servertag", 9, new_pv(dcc->servertag), 0); - hv_store(hv, "mynick", 6, new_pv(dcc->mynick), 0); - hv_store(hv, "nick", 4, new_pv(dcc->nick), 0); + (void) hv_store(hv, "server", 6, iobject_bless(dcc->server), 0); + (void) hv_store(hv, "servertag", 9, new_pv(dcc->servertag), 0); + (void) hv_store(hv, "mynick", 6, new_pv(dcc->mynick), 0); + (void) hv_store(hv, "nick", 4, new_pv(dcc->nick), 0); - hv_store(hv, "chat", 4, simple_iobject_bless(dcc->chat), 0); - hv_store(hv, "target", 6, new_pv(dcc->target), 0); - hv_store(hv, "arg", 3, new_pv(dcc->arg), 0); + (void) hv_store(hv, "chat", 4, simple_iobject_bless(dcc->chat), 0); + (void) hv_store(hv, "target", 6, new_pv(dcc->target), 0); + (void) hv_store(hv, "arg", 3, new_pv(dcc->arg), 0); - hv_store(hv, "addr", 4, new_pv(dcc->addrstr), 0); - hv_store(hv, "port", 4, newSViv(dcc->port), 0); + (void) hv_store(hv, "addr", 4, new_pv(dcc->addrstr), 0); + (void) hv_store(hv, "port", 4, newSViv(dcc->port), 0); - hv_store(hv, "starttime", 9, newSViv(dcc->starttime), 0); - hv_store(hv, "transfd", 7, newSViv(dcc->transfd), 0); + (void) hv_store(hv, "starttime", 9, newSViv(dcc->starttime), 0); + (void) hv_store(hv, "transfd", 7, newSViv(dcc->transfd), 0); } static void perl_dcc_chat_fill_hash(HV *hv, CHAT_DCC_REC *dcc) { perl_dcc_fill_hash(hv, (DCC_REC *) dcc); - hv_store(hv, "id", 2, new_pv(dcc->id), 0); - hv_store(hv, "mirc_ctcp", 9, newSViv(dcc->mirc_ctcp), 0); - hv_store(hv, "connection_lost", 15, newSViv(dcc->connection_lost), 0); + (void) hv_store(hv, "id", 2, new_pv(dcc->id), 0); + (void) hv_store(hv, "mirc_ctcp", 9, newSViv(dcc->mirc_ctcp), 0); + (void) hv_store(hv, "connection_lost", 15, newSViv(dcc->connection_lost), 0); } static void perl_dcc_file_fill_hash(HV *hv, FILE_DCC_REC *dcc) { perl_dcc_fill_hash(hv, (DCC_REC *) dcc); - hv_store(hv, "size", 4, newSViv(dcc->size), 0); - hv_store(hv, "skipped", 7, newSViv(dcc->skipped), 0); + (void) hv_store(hv, "size", 4, newSViv(dcc->size), 0); + (void) hv_store(hv, "skipped", 7, newSViv(dcc->skipped), 0); } static void perl_dcc_get_fill_hash(HV *hv, GET_DCC_REC *dcc) { perl_dcc_file_fill_hash(hv, (FILE_DCC_REC *) dcc); - hv_store(hv, "get_type", 8, newSViv(dcc->get_type), 0); - hv_store(hv, "file", 4, new_pv(dcc->file), 0); - hv_store(hv, "file_quoted", 11, newSViv(dcc->file_quoted), 0); + (void) hv_store(hv, "get_type", 8, newSViv(dcc->get_type), 0); + (void) hv_store(hv, "file", 4, new_pv(dcc->file), 0); + (void) hv_store(hv, "file_quoted", 11, newSViv(dcc->file_quoted), 0); } static void perl_dcc_send_fill_hash(HV *hv, SEND_DCC_REC *dcc) { perl_dcc_file_fill_hash(hv, (FILE_DCC_REC *) dcc); - hv_store(hv, "file_quoted", 11, newSViv(dcc->file_quoted), 0); - hv_store(hv, "waitforend", 10, newSViv(dcc->waitforend), 0); - hv_store(hv, "gotalldata", 10, newSViv(dcc->gotalldata), 0); + (void) hv_store(hv, "file_quoted", 11, newSViv(dcc->file_quoted), 0); + (void) hv_store(hv, "waitforend", 10, newSViv(dcc->waitforend), 0); + (void) hv_store(hv, "gotalldata", 10, newSViv(dcc->gotalldata), 0); } static void perl_netsplit_fill_hash(HV *hv, NETSPLIT_REC *netsplit) @@ -97,11 +97,11 @@ static void perl_netsplit_fill_hash(HV *hv, NETSPLIT_REC *netsplit) AV *av; GSList *tmp; - hv_store(hv, "nick", 4, new_pv(netsplit->nick), 0); - hv_store(hv, "address", 7, new_pv(netsplit->address), 0); - hv_store(hv, "destroy", 7, newSViv(netsplit->destroy), 0); + (void) hv_store(hv, "nick", 4, new_pv(netsplit->nick), 0); + (void) hv_store(hv, "address", 7, new_pv(netsplit->address), 0); + (void) hv_store(hv, "destroy", 7, newSViv(netsplit->destroy), 0); - hv_store(hv, "server", 6, + (void) hv_store(hv, "server", 6, plain_bless(netsplit->server, "Irssi::Irc::Netsplitserver"), 0); @@ -110,22 +110,22 @@ static void perl_netsplit_fill_hash(HV *hv, NETSPLIT_REC *netsplit) av_push(av, plain_bless(tmp->data, "Irssi::Irc::Netsplitchannel")); } - hv_store(hv, "channels", 8, newRV_noinc((SV*)av), 0); + (void) hv_store(hv, "channels", 8, newRV_noinc((SV*)av), 0); } static void perl_netsplit_server_fill_hash(HV *hv, NETSPLIT_SERVER_REC *rec) { - hv_store(hv, "server", 6, new_pv(rec->server), 0); - hv_store(hv, "destserver", 10, new_pv(rec->destserver), 0); - hv_store(hv, "count", 5, newSViv(rec->count), 0); + (void) hv_store(hv, "server", 6, new_pv(rec->server), 0); + (void) hv_store(hv, "destserver", 10, new_pv(rec->destserver), 0); + (void) hv_store(hv, "count", 5, newSViv(rec->count), 0); } static void perl_netsplit_channel_fill_hash(HV *hv, NETSPLIT_CHAN_REC *rec) { - hv_store(hv, "name", 4, new_pv(rec->name), 0); - hv_store(hv, "op", 2, newSViv(rec->op), 0); - hv_store(hv, "halfop", 6, newSViv(rec->halfop), 0); - hv_store(hv, "voice", 5, newSViv(rec->voice), 0); + (void) hv_store(hv, "name", 4, new_pv(rec->name), 0); + (void) hv_store(hv, "op", 2, newSViv(rec->op), 0); + (void) hv_store(hv, "halfop", 6, newSViv(rec->halfop), 0); + (void) hv_store(hv, "voice", 5, newSViv(rec->voice), 0); } static void perl_notifylist_fill_hash(HV *hv, NOTIFYLIST_REC *notify) @@ -133,8 +133,8 @@ static void perl_notifylist_fill_hash(HV *hv, NOTIFYLIST_REC *notify) AV *av; char **tmp; - hv_store(hv, "mask", 4, new_pv(notify->mask), 0); - hv_store(hv, "away_check", 10, newSViv(notify->away_check), 0); + (void) hv_store(hv, "mask", 4, new_pv(notify->mask), 0); + (void) hv_store(hv, "away_check", 10, newSViv(notify->away_check), 0); av = newAV(); if (notify->ircnets != NULL) { @@ -142,20 +142,20 @@ static void perl_notifylist_fill_hash(HV *hv, NOTIFYLIST_REC *notify) av_push(av, new_pv(*tmp)); } } - hv_store(hv, "ircnets", 7, newRV_noinc((SV*)av), 0); + (void) hv_store(hv, "ircnets", 7, newRV_noinc((SV*)av), 0); } static void perl_client_fill_hash(HV *hv, CLIENT_REC *client) { - hv_store(hv, "nick", 4, new_pv(client->nick), 0); - hv_store(hv, "host", 4, new_pv(client->host), 0); - hv_store(hv, "proxy_address", 13, new_pv(client->proxy_address), 0); - hv_store(hv, "server", 6, iobject_bless(client->server), 0); - hv_store(hv, "pass_sent", 9, newSViv(client->pass_sent), 0); - hv_store(hv, "user_sent", 9, newSViv(client->user_sent), 0); - hv_store(hv, "connected", 9, newSViv(client->connected), 0); - hv_store(hv, "want_ctcp", 9, newSViv(client->want_ctcp), 0); - hv_store(hv, "ircnet", 6, new_pv(client->listen->ircnet), 0); + (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, "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); + (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, "ircnet", 6, new_pv(client->listen->ircnet), 0); } static PLAIN_OBJECT_INIT_REC irc_plains[] = { diff --git a/src/perl/perl-common.c b/src/perl/perl-common.c index 0a8a5d92..dcda3bb5 100644 --- a/src/perl/perl-common.c +++ b/src/perl/perl-common.c @@ -135,7 +135,7 @@ SV *irssi_bless_iobject(int type, int chat_type, void *object) stash = gv_stashpv(rec->stash, 1); hv = newHV(); - hv_store(hv, "_irssi", 6, create_sv_ptr(object), 0); + (void) hv_store(hv, "_irssi", 6, create_sv_ptr(object), 0); rec->fill_func(hv, object); return sv_bless(newRV_noinc((SV*)hv), stash); } @@ -148,7 +148,7 @@ SV *irssi_bless_plain(const char *stash, void *object) fill_func = g_hash_table_lookup(plain_stashes, stash); hv = newHV(); - hv_store(hv, "_irssi", 6, create_sv_ptr(object), 0); + (void) hv_store(hv, "_irssi", 6, create_sv_ptr(object), 0); if (fill_func != NULL) fill_func(hv, object); return sv_bless(newRV_noinc((SV*)hv), gv_stashpv((char *)stash, 1)); @@ -264,17 +264,17 @@ void perl_chatnet_fill_hash(HV *hv, CHATNET_REC *chatnet) type = "CHATNET"; chat_type = (char *) chat_protocol_find_id(chatnet->chat_type)->name; - hv_store(hv, "type", 4, new_pv(type), 0); - hv_store(hv, "chat_type", 9, new_pv(chat_type), 0); + (void) hv_store(hv, "type", 4, new_pv(type), 0); + (void) hv_store(hv, "chat_type", 9, new_pv(chat_type), 0); - hv_store(hv, "name", 4, new_pv(chatnet->name), 0); + (void) hv_store(hv, "name", 4, new_pv(chatnet->name), 0); - hv_store(hv, "nick", 4, new_pv(chatnet->nick), 0); - hv_store(hv, "username", 8, new_pv(chatnet->username), 0); - hv_store(hv, "realname", 8, new_pv(chatnet->realname), 0); + (void) hv_store(hv, "nick", 4, new_pv(chatnet->nick), 0); + (void) hv_store(hv, "username", 8, new_pv(chatnet->username), 0); + (void) hv_store(hv, "realname", 8, new_pv(chatnet->realname), 0); - hv_store(hv, "own_host", 8, new_pv(chatnet->own_host), 0); - hv_store(hv, "autosendcmd", 11, new_pv(chatnet->autosendcmd), 0); + (void) hv_store(hv, "own_host", 8, new_pv(chatnet->own_host), 0); + (void) hv_store(hv, "autosendcmd", 11, new_pv(chatnet->autosendcmd), 0); } void perl_connect_fill_hash(HV *hv, SERVER_CONNECT_REC *conn) @@ -287,25 +287,25 @@ void perl_connect_fill_hash(HV *hv, SERVER_CONNECT_REC *conn) type = "SERVER CONNECT"; chat_type = (char *) chat_protocol_find_id(conn->chat_type)->name; - hv_store(hv, "type", 4, new_pv(type), 0); - hv_store(hv, "chat_type", 9, new_pv(chat_type), 0); + (void) hv_store(hv, "type", 4, new_pv(type), 0); + (void) hv_store(hv, "chat_type", 9, new_pv(chat_type), 0); - hv_store(hv, "tag", 3, new_pv(conn->tag), 0); - hv_store(hv, "address", 7, new_pv(conn->address), 0); - hv_store(hv, "port", 4, newSViv(conn->port), 0); - hv_store(hv, "chatnet", 7, new_pv(conn->chatnet), 0); + (void) hv_store(hv, "tag", 3, new_pv(conn->tag), 0); + (void) hv_store(hv, "address", 7, new_pv(conn->address), 0); + (void) hv_store(hv, "port", 4, newSViv(conn->port), 0); + (void) hv_store(hv, "chatnet", 7, new_pv(conn->chatnet), 0); - hv_store(hv, "password", 8, new_pv(conn->password), 0); - hv_store(hv, "wanted_nick", 11, new_pv(conn->nick), 0); - hv_store(hv, "username", 8, new_pv(conn->username), 0); - hv_store(hv, "realname", 8, new_pv(conn->realname), 0); + (void) hv_store(hv, "password", 8, new_pv(conn->password), 0); + (void) hv_store(hv, "wanted_nick", 11, new_pv(conn->nick), 0); + (void) hv_store(hv, "username", 8, new_pv(conn->username), 0); + (void) hv_store(hv, "realname", 8, new_pv(conn->realname), 0); - hv_store(hv, "reconnection", 12, newSViv(conn->reconnection), 0); - hv_store(hv, "no_autojoin_channels", 20, newSViv(conn->no_autojoin_channels), 0); - hv_store(hv, "no_autosendcmd", 14, newSViv(conn->no_autosendcmd), 0); - hv_store(hv, "unix_socket", 11, newSViv(conn->unix_socket), 0); - hv_store(hv, "use_ssl", 7, newSViv(conn->use_ssl), 0); - hv_store(hv, "no_connect", 10, newSViv(conn->no_connect), 0); + (void) hv_store(hv, "reconnection", 12, newSViv(conn->reconnection), 0); + (void) hv_store(hv, "no_autojoin_channels", 20, newSViv(conn->no_autojoin_channels), 0); + (void) hv_store(hv, "no_autosendcmd", 14, newSViv(conn->no_autosendcmd), 0); + (void) hv_store(hv, "unix_socket", 11, newSViv(conn->unix_socket), 0); + (void) hv_store(hv, "use_ssl", 7, newSViv(conn->use_ssl), 0); + (void) hv_store(hv, "no_connect", 10, newSViv(conn->no_connect), 0); } void perl_server_fill_hash(HV *hv, SERVER_REC *server) @@ -319,28 +319,28 @@ void perl_server_fill_hash(HV *hv, SERVER_REC *server) perl_connect_fill_hash(hv, server->connrec); type = "SERVER"; - hv_store(hv, "type", 4, new_pv(type), 0); + (void) hv_store(hv, "type", 4, new_pv(type), 0); - hv_store(hv, "connect_time", 12, newSViv(server->connect_time), 0); - hv_store(hv, "real_connect_time", 17, newSViv(server->real_connect_time), 0); + (void) hv_store(hv, "connect_time", 12, newSViv(server->connect_time), 0); + (void) hv_store(hv, "real_connect_time", 17, newSViv(server->real_connect_time), 0); - hv_store(hv, "tag", 3, new_pv(server->tag), 0); - hv_store(hv, "nick", 4, new_pv(server->nick), 0); + (void) hv_store(hv, "tag", 3, new_pv(server->tag), 0); + (void) hv_store(hv, "nick", 4, new_pv(server->nick), 0); - hv_store(hv, "connected", 9, newSViv(server->connected), 0); - hv_store(hv, "connection_lost", 15, newSViv(server->connection_lost), 0); + (void) hv_store(hv, "connected", 9, newSViv(server->connected), 0); + (void) hv_store(hv, "connection_lost", 15, newSViv(server->connection_lost), 0); stash = gv_stashpv("Irssi::Rawlog", 0); - hv_store(hv, "rawlog", 6, sv_bless(newRV_noinc(newSViv((IV)server->rawlog)), stash), 0); + (void) hv_store(hv, "rawlog", 6, sv_bless(newRV_noinc(newSViv((IV)server->rawlog)), stash), 0); - hv_store(hv, "version", 7, new_pv(server->version), 0); - hv_store(hv, "away_reason", 11, new_pv(server->away_reason), 0); - hv_store(hv, "last_invite", 11, new_pv(server->last_invite), 0); - hv_store(hv, "server_operator", 15, newSViv(server->server_operator), 0); - hv_store(hv, "usermode_away", 13, newSViv(server->usermode_away), 0); - hv_store(hv, "banned", 6, newSViv(server->banned), 0); + (void) hv_store(hv, "version", 7, new_pv(server->version), 0); + (void) hv_store(hv, "away_reason", 11, new_pv(server->away_reason), 0); + (void) hv_store(hv, "last_invite", 11, new_pv(server->last_invite), 0); + (void) hv_store(hv, "server_operator", 15, newSViv(server->server_operator), 0); + (void) hv_store(hv, "usermode_away", 13, newSViv(server->usermode_away), 0); + (void) hv_store(hv, "banned", 6, newSViv(server->banned), 0); - hv_store(hv, "lag", 3, newSViv(server->lag), 0); + (void) hv_store(hv, "lag", 3, newSViv(server->lag), 0); } void perl_window_item_fill_hash(HV *hv, WI_ITEM_REC *item) @@ -353,17 +353,17 @@ void perl_window_item_fill_hash(HV *hv, WI_ITEM_REC *item) type = (char *) module_find_id_str("WINDOW ITEM TYPE", item->type); chat_type = (char *) chat_protocol_find_id(item->chat_type)->name; - hv_store(hv, "type", 4, new_pv(type), 0); - hv_store(hv, "chat_type", 9, new_pv(chat_type), 0); + (void) hv_store(hv, "type", 4, new_pv(type), 0); + (void) hv_store(hv, "chat_type", 9, new_pv(chat_type), 0); if (item->server != NULL) { - hv_store(hv, "server", 6, iobject_bless(item->server), 0); + (void) hv_store(hv, "server", 6, iobject_bless(item->server), 0); } - hv_store(hv, "visible_name", 12, new_pv(item->visible_name), 0); + (void) hv_store(hv, "visible_name", 12, new_pv(item->visible_name), 0); - hv_store(hv, "createtime", 10, newSViv(item->createtime), 0); - hv_store(hv, "data_level", 10, newSViv(item->data_level), 0); - hv_store(hv, "hilight_color", 13, new_pv(item->hilight_color), 0); + (void) hv_store(hv, "createtime", 10, newSViv(item->createtime), 0); + (void) hv_store(hv, "data_level", 10, newSViv(item->data_level), 0); + (void) hv_store(hv, "hilight_color", 13, new_pv(item->hilight_color), 0); } void perl_channel_fill_hash(HV *hv, CHANNEL_REC *channel) @@ -374,26 +374,26 @@ void perl_channel_fill_hash(HV *hv, CHANNEL_REC *channel) perl_window_item_fill_hash(hv, (WI_ITEM_REC *) channel); if (channel->ownnick != NULL) - hv_store(hv, "ownnick", 7, iobject_bless(channel->ownnick), 0); + (void) hv_store(hv, "ownnick", 7, iobject_bless(channel->ownnick), 0); - hv_store(hv, "name", 4, new_pv(channel->name), 0); - hv_store(hv, "topic", 5, new_pv(channel->topic), 0); - hv_store(hv, "topic_by", 8, new_pv(channel->topic_by), 0); - hv_store(hv, "topic_time", 10, newSViv(channel->topic_time), 0); + (void) hv_store(hv, "name", 4, new_pv(channel->name), 0); + (void) hv_store(hv, "topic", 5, new_pv(channel->topic), 0); + (void) hv_store(hv, "topic_by", 8, new_pv(channel->topic_by), 0); + (void) hv_store(hv, "topic_time", 10, newSViv(channel->topic_time), 0); - hv_store(hv, "no_modes", 8, newSViv(channel->no_modes), 0); - hv_store(hv, "mode", 4, new_pv(channel->mode), 0); - hv_store(hv, "limit", 5, newSViv(channel->limit), 0); - hv_store(hv, "key", 3, new_pv(channel->key), 0); + (void) hv_store(hv, "no_modes", 8, newSViv(channel->no_modes), 0); + (void) hv_store(hv, "mode", 4, new_pv(channel->mode), 0); + (void) hv_store(hv, "limit", 5, newSViv(channel->limit), 0); + (void) hv_store(hv, "key", 3, new_pv(channel->key), 0); - hv_store(hv, "chanop", 6, newSViv(channel->chanop), 0); - hv_store(hv, "names_got", 9, newSViv(channel->names_got), 0); - hv_store(hv, "wholist", 7, newSViv(channel->wholist), 0); - hv_store(hv, "synced", 6, newSViv(channel->synced), 0); + (void) hv_store(hv, "chanop", 6, newSViv(channel->chanop), 0); + (void) hv_store(hv, "names_got", 9, newSViv(channel->names_got), 0); + (void) hv_store(hv, "wholist", 7, newSViv(channel->wholist), 0); + (void) hv_store(hv, "synced", 6, newSViv(channel->synced), 0); - hv_store(hv, "joined", 6, newSViv(channel->joined), 0); - hv_store(hv, "left", 4, newSViv(channel->left), 0); - hv_store(hv, "kicked", 6, newSViv(channel->kicked), 0); + (void) hv_store(hv, "joined", 6, newSViv(channel->joined), 0); + (void) hv_store(hv, "left", 4, newSViv(channel->left), 0); + (void) hv_store(hv, "kicked", 6, newSViv(channel->kicked), 0); } void perl_query_fill_hash(HV *hv, QUERY_REC *query) @@ -403,11 +403,11 @@ void perl_query_fill_hash(HV *hv, QUERY_REC *query) perl_window_item_fill_hash(hv, (WI_ITEM_REC *) query); - hv_store(hv, "name", 4, new_pv(query->name), 0); - hv_store(hv, "last_unread_msg", 15, newSViv(query->last_unread_msg), 0); - hv_store(hv, "address", 7, new_pv(query->address), 0); - hv_store(hv, "server_tag", 10, new_pv(query->server_tag), 0); - hv_store(hv, "unwanted", 8, newSViv(query->unwanted), 0); + (void) hv_store(hv, "name", 4, new_pv(query->name), 0); + (void) hv_store(hv, "last_unread_msg", 15, newSViv(query->last_unread_msg), 0); + (void) hv_store(hv, "address", 7, new_pv(query->address), 0); + (void) hv_store(hv, "server_tag", 10, new_pv(query->server_tag), 0); + (void) hv_store(hv, "unwanted", 8, newSViv(query->unwanted), 0); } void perl_nick_fill_hash(HV *hv, NICK_REC *nick) @@ -420,31 +420,31 @@ void perl_nick_fill_hash(HV *hv, NICK_REC *nick) type = "NICK"; chat_type = (char *) chat_protocol_find_id(nick->chat_type)->name; - hv_store(hv, "type", 4, new_pv(type), 0); - hv_store(hv, "chat_type", 9, new_pv(chat_type), 0); + (void) hv_store(hv, "type", 4, new_pv(type), 0); + (void) hv_store(hv, "chat_type", 9, new_pv(chat_type), 0); - hv_store(hv, "nick", 4, new_pv(nick->nick), 0); - hv_store(hv, "host", 4, new_pv(nick->host), 0); - hv_store(hv, "realname", 8, new_pv(nick->realname), 0); - hv_store(hv, "hops", 4, newSViv(nick->hops), 0); + (void) hv_store(hv, "nick", 4, new_pv(nick->nick), 0); + (void) hv_store(hv, "host", 4, new_pv(nick->host), 0); + (void) hv_store(hv, "realname", 8, new_pv(nick->realname), 0); + (void) hv_store(hv, "hops", 4, newSViv(nick->hops), 0); - hv_store(hv, "gone", 4, newSViv(nick->gone), 0); - hv_store(hv, "serverop", 8, newSViv(nick->serverop), 0); + (void) hv_store(hv, "gone", 4, newSViv(nick->gone), 0); + (void) hv_store(hv, "serverop", 8, newSViv(nick->serverop), 0); - hv_store(hv, "op", 2, newSViv(nick->op), 0); - hv_store(hv, "halfop", 6, newSViv(nick->halfop), 0); - hv_store(hv, "voice", 5, newSViv(nick->voice), 0); - hv_store(hv, "other", 5, newSViv(nick->prefixes[0]), 0); - hv_store(hv, "prefixes", 8, new_pv(nick->prefixes), 0); + (void) hv_store(hv, "op", 2, newSViv(nick->op), 0); + (void) hv_store(hv, "halfop", 6, newSViv(nick->halfop), 0); + (void) hv_store(hv, "voice", 5, newSViv(nick->voice), 0); + (void) hv_store(hv, "other", 5, newSViv(nick->prefixes[0]), 0); + (void) hv_store(hv, "prefixes", 8, new_pv(nick->prefixes), 0); - hv_store(hv, "last_check", 10, newSViv(nick->last_check), 0); - hv_store(hv, "send_massjoin", 13, newSViv(nick->send_massjoin), 0); + (void) hv_store(hv, "last_check", 10, newSViv(nick->last_check), 0); + (void) hv_store(hv, "send_massjoin", 13, newSViv(nick->send_massjoin), 0); } static void perl_command_fill_hash(HV *hv, COMMAND_REC *cmd) { - hv_store(hv, "category", 8, new_pv(cmd->category), 0); - hv_store(hv, "cmd", 3, new_pv(cmd->cmd), 0); + (void) hv_store(hv, "category", 8, new_pv(cmd->category), 0); + (void) hv_store(hv, "cmd", 3, new_pv(cmd->cmd), 0); } static void perl_ignore_fill_hash(HV *hv, IGNORE_REC *ignore) @@ -452,22 +452,22 @@ static void perl_ignore_fill_hash(HV *hv, IGNORE_REC *ignore) AV *av; char **tmp; - hv_store(hv, "mask", 4, new_pv(ignore->mask), 0); - hv_store(hv, "servertag", 9, new_pv(ignore->servertag), 0); + (void) hv_store(hv, "mask", 4, new_pv(ignore->mask), 0); + (void) hv_store(hv, "servertag", 9, new_pv(ignore->servertag), 0); av = newAV(); if (ignore->channels != NULL) { for (tmp = ignore->channels; *tmp != NULL; tmp++) { av_push(av, new_pv(*tmp)); } } - hv_store(hv, "channels", 8, newRV_noinc((SV*)av), 0); - hv_store(hv, "pattern", 7, new_pv(ignore->pattern), 0); + (void) hv_store(hv, "channels", 8, newRV_noinc((SV*)av), 0); + (void) hv_store(hv, "pattern", 7, new_pv(ignore->pattern), 0); - hv_store(hv, "level", 5, newSViv(ignore->level), 0); + (void) hv_store(hv, "level", 5, newSViv(ignore->level), 0); - hv_store(hv, "exception", 9, newSViv(ignore->exception), 0); - hv_store(hv, "regexp", 6, newSViv(ignore->regexp), 0); - hv_store(hv, "fullword", 8, newSViv(ignore->fullword), 0); + (void) hv_store(hv, "exception", 9, newSViv(ignore->exception), 0); + (void) hv_store(hv, "regexp", 6, newSViv(ignore->regexp), 0); + (void) hv_store(hv, "fullword", 8, newSViv(ignore->fullword), 0); } static void perl_log_fill_hash(HV *hv, LOG_REC *log) @@ -475,33 +475,33 @@ static void perl_log_fill_hash(HV *hv, LOG_REC *log) AV *av; GSList *tmp; - hv_store(hv, "fname", 5, new_pv(log->fname), 0); - hv_store(hv, "real_fname", 10, new_pv(log->real_fname), 0); - hv_store(hv, "opened", 6, newSViv(log->opened), 0); - hv_store(hv, "level", 5, newSViv(log->level), 0); - hv_store(hv, "last", 4, newSViv(log->last), 0); - hv_store(hv, "autoopen", 8, newSViv(log->autoopen), 0); - hv_store(hv, "failed", 6, newSViv(log->failed), 0); - hv_store(hv, "temp", 4, newSViv(log->temp), 0); + (void) hv_store(hv, "fname", 5, new_pv(log->fname), 0); + (void) hv_store(hv, "real_fname", 10, new_pv(log->real_fname), 0); + (void) hv_store(hv, "opened", 6, newSViv(log->opened), 0); + (void) hv_store(hv, "level", 5, newSViv(log->level), 0); + (void) hv_store(hv, "last", 4, newSViv(log->last), 0); + (void) hv_store(hv, "autoopen", 8, newSViv(log->autoopen), 0); + (void) hv_store(hv, "failed", 6, newSViv(log->failed), 0); + (void) hv_store(hv, "temp", 4, newSViv(log->temp), 0); av = newAV(); for (tmp = log->items; tmp != NULL; tmp = tmp->next) { av_push(av, plain_bless(tmp->data, "Irssi::Logitem")); } - hv_store(hv, "items", 5, newRV_noinc((SV*)av), 0); + (void) hv_store(hv, "items", 5, newRV_noinc((SV*)av), 0); } static void perl_log_item_fill_hash(HV *hv, LOG_ITEM_REC *item) { - hv_store(hv, "type", 4, newSViv(item->type), 0); - hv_store(hv, "name", 4, new_pv(item->name), 0); - hv_store(hv, "servertag", 9, new_pv(item->servertag), 0); + (void) hv_store(hv, "type", 4, newSViv(item->type), 0); + (void) hv_store(hv, "name", 4, new_pv(item->name), 0); + (void) hv_store(hv, "servertag", 9, new_pv(item->servertag), 0); } static void perl_rawlog_fill_hash(HV *hv, RAWLOG_REC *rawlog) { - hv_store(hv, "logging", 7, newSViv(rawlog->logging), 0); - hv_store(hv, "nlines", 6, newSViv(rawlog->nlines), 0); + (void) hv_store(hv, "logging", 7, newSViv(rawlog->logging), 0); + (void) hv_store(hv, "nlines", 6, newSViv(rawlog->nlines), 0); } static void perl_reconnect_fill_hash(HV *hv, RECONNECT_REC *reconnect) @@ -511,18 +511,18 @@ static void perl_reconnect_fill_hash(HV *hv, RECONNECT_REC *reconnect) perl_connect_fill_hash(hv, reconnect->conn); type = "RECONNECT"; - hv_store(hv, "type", 4, new_pv(type), 0); + (void) hv_store(hv, "type", 4, new_pv(type), 0); - hv_store(hv, "tag", 3, newSViv(reconnect->tag), 0); - hv_store(hv, "next_connect", 12, newSViv(reconnect->next_connect), 0); + (void) hv_store(hv, "tag", 3, newSViv(reconnect->tag), 0); + (void) hv_store(hv, "next_connect", 12, newSViv(reconnect->next_connect), 0); } static void perl_script_fill_hash(HV *hv, PERL_SCRIPT_REC *script) { - hv_store(hv, "name", 4, new_pv(script->name), 0); - hv_store(hv, "package", 7, new_pv(script->package), 0); - hv_store(hv, "path", 4, new_pv(script->path), 0); - hv_store(hv, "data", 4, new_pv(script->data), 0); + (void) hv_store(hv, "name", 4, new_pv(script->name), 0); + (void) hv_store(hv, "package", 7, new_pv(script->package), 0); + (void) hv_store(hv, "path", 4, new_pv(script->path), 0); + (void) hv_store(hv, "data", 4, new_pv(script->data), 0); } static void remove_newlines(char *str) diff --git a/src/perl/textui/Statusbar.xs b/src/perl/textui/Statusbar.xs index 620fad9a..a449e11d 100644 --- a/src/perl/textui/Statusbar.xs +++ b/src/perl/textui/Statusbar.xs @@ -160,5 +160,5 @@ CODE: *str == '\0' ? NULL : str, data, escape_vars); hv = hvref(ST(0)); - hv_store(hv, "min_size", 8, newSViv(item->min_size), 0); - hv_store(hv, "max_size", 8, newSViv(item->max_size), 0); + (void) hv_store(hv, "min_size", 8, newSViv(item->min_size), 0); + (void) hv_store(hv, "max_size", 8, newSViv(item->max_size), 0); diff --git a/src/perl/textui/TextUI.xs b/src/perl/textui/TextUI.xs index ae986aaf..5d2c8a7f 100644 --- a/src/perl/textui/TextUI.xs +++ b/src/perl/textui/TextUI.xs @@ -8,72 +8,72 @@ static int initialized = FALSE; static void perl_main_window_fill_hash(HV *hv, MAIN_WINDOW_REC *window) { - hv_store(hv, "active", 6, plain_bless(window->active, "Irssi::UI::Window"), 0); + (void) hv_store(hv, "active", 6, plain_bless(window->active, "Irssi::UI::Window"), 0); - hv_store(hv, "first_line", 10, newSViv(window->first_line), 0); - hv_store(hv, "last_line", 9, newSViv(window->last_line), 0); - hv_store(hv, "width", 5, newSViv(window->width), 0); - hv_store(hv, "height", 6, newSViv(window->height), 0); + (void) hv_store(hv, "first_line", 10, newSViv(window->first_line), 0); + (void) hv_store(hv, "last_line", 9, newSViv(window->last_line), 0); + (void) hv_store(hv, "width", 5, newSViv(window->width), 0); + (void) hv_store(hv, "height", 6, newSViv(window->height), 0); - hv_store(hv, "statusbar_lines", 15, newSViv(window->statusbar_lines), 0); + (void) hv_store(hv, "statusbar_lines", 15, newSViv(window->statusbar_lines), 0); } static void perl_text_buffer_fill_hash(HV *hv, TEXT_BUFFER_REC *buffer) { - hv_store(hv, "first_line", 10, plain_bless(buffer->first_line, "Irssi::TextUI::Line"), 0); - hv_store(hv, "lines_count", 11, newSViv(buffer->lines_count), 0); - hv_store(hv, "cur_line", 8, plain_bless(buffer->cur_line, "Irssi::TextUI::Line"), 0); - hv_store(hv, "last_eol", 8, newSViv(buffer->last_eol), 0); + (void) hv_store(hv, "first_line", 10, plain_bless(buffer->first_line, "Irssi::TextUI::Line"), 0); + (void) hv_store(hv, "lines_count", 11, newSViv(buffer->lines_count), 0); + (void) hv_store(hv, "cur_line", 8, plain_bless(buffer->cur_line, "Irssi::TextUI::Line"), 0); + (void) hv_store(hv, "last_eol", 8, newSViv(buffer->last_eol), 0); } static void perl_text_buffer_view_fill_hash(HV *hv, TEXT_BUFFER_VIEW_REC *view) { - hv_store(hv, "buffer", 6, plain_bless(view->buffer, "Irssi::TextUI::TextBuffer"), 0); - hv_store(hv, "width", 5, newSViv(view->width), 0); - hv_store(hv, "height", 6, newSViv(view->height), 0); + (void) hv_store(hv, "buffer", 6, plain_bless(view->buffer, "Irssi::TextUI::TextBuffer"), 0); + (void) hv_store(hv, "width", 5, newSViv(view->width), 0); + (void) hv_store(hv, "height", 6, newSViv(view->height), 0); - hv_store(hv, "default_indent", 14, newSViv(view->default_indent), 0); - hv_store(hv, "longword_noindent", 17, newSViv(view->longword_noindent), 0); - hv_store(hv, "scroll", 6, newSViv(view->scroll), 0); + (void) hv_store(hv, "default_indent", 14, newSViv(view->default_indent), 0); + (void) hv_store(hv, "longword_noindent", 17, newSViv(view->longword_noindent), 0); + (void) hv_store(hv, "scroll", 6, newSViv(view->scroll), 0); - hv_store(hv, "ypos", 4, newSViv(view->ypos), 0); + (void) hv_store(hv, "ypos", 4, newSViv(view->ypos), 0); - hv_store(hv, "startline", 9, plain_bless(view->startline, "Irssi::TextUI::Line"), 0); - hv_store(hv, "subline", 7, newSViv(view->subline), 0); + (void) hv_store(hv, "startline", 9, plain_bless(view->startline, "Irssi::TextUI::Line"), 0); + (void) hv_store(hv, "subline", 7, newSViv(view->subline), 0); - hv_store(hv, "bottom_startline", 16, plain_bless(view->bottom_startline, "Irssi::TextUI::Line"), 0); - hv_store(hv, "bottom_subline", 14, newSViv(view->bottom_subline), 0); + (void) hv_store(hv, "bottom_startline", 16, plain_bless(view->bottom_startline, "Irssi::TextUI::Line"), 0); + (void) hv_store(hv, "bottom_subline", 14, newSViv(view->bottom_subline), 0); - hv_store(hv, "empty_linecount", 15, newSViv(view->empty_linecount), 0); - hv_store(hv, "bottom", 6, newSViv(view->bottom), 0); + (void) hv_store(hv, "empty_linecount", 15, newSViv(view->empty_linecount), 0); + (void) hv_store(hv, "bottom", 6, newSViv(view->bottom), 0); } static void perl_line_fill_hash(HV *hv, LINE_REC *line) { - hv_store(hv, "info", 4, plain_bless(&line->info, "Irssi::TextUI::LineInfo"), 0); + (void) hv_store(hv, "info", 4, plain_bless(&line->info, "Irssi::TextUI::LineInfo"), 0); } static void perl_line_cache_fill_hash(HV *hv, LINE_CACHE_REC *cache) { - hv_store(hv, "last_access", 11, newSViv(cache->last_access), 0); - hv_store(hv, "count", 5, newSViv(cache->count), 0); + (void) hv_store(hv, "last_access", 11, newSViv(cache->last_access), 0); + (void) hv_store(hv, "count", 5, newSViv(cache->count), 0); /*LINE_CACHE_SUB_REC lines[1];*/ } static void perl_line_info_fill_hash(HV *hv, LINE_INFO_REC *info) { - hv_store(hv, "level", 5, newSViv(info->level), 0); - hv_store(hv, "time", 4, newSViv(info->time), 0); + (void) hv_store(hv, "level", 5, newSViv(info->level), 0); + (void) hv_store(hv, "time", 4, newSViv(info->time), 0); } static void perl_statusbar_item_fill_hash(HV *hv, SBAR_ITEM_REC *item) { - hv_store(hv, "min_size", 8, newSViv(item->min_size), 0); - hv_store(hv, "max_size", 8, newSViv(item->max_size), 0); - hv_store(hv, "xpos", 4, newSViv(item->xpos), 0); - hv_store(hv, "size", 4, newSViv(item->size), 0); + (void) hv_store(hv, "min_size", 8, newSViv(item->min_size), 0); + (void) hv_store(hv, "max_size", 8, newSViv(item->max_size), 0); + (void) hv_store(hv, "xpos", 4, newSViv(item->xpos), 0); + (void) hv_store(hv, "size", 4, newSViv(item->size), 0); if (item->bar->parent_window != NULL) - hv_store(hv, "window", 6, plain_bless(item->bar->parent_window->active, "Irssi::UI::Window"), 0); + (void) hv_store(hv, "window", 6, plain_bless(item->bar->parent_window->active, "Irssi::UI::Window"), 0); } static PLAIN_OBJECT_INIT_REC textui_plains[] = { diff --git a/src/perl/ui/UI.xs b/src/perl/ui/UI.xs index 2e32762c..9db57e98 100644 --- a/src/perl/ui/UI.xs +++ b/src/perl/ui/UI.xs @@ -8,60 +8,60 @@ static int initialized = FALSE; static void perl_process_fill_hash(HV *hv, PROCESS_REC *process) { - hv_store(hv, "id", 2, newSViv(process->id), 0); - hv_store(hv, "name", 4, new_pv(process->name), 0); - hv_store(hv, "args", 4, new_pv(process->args), 0); + (void) hv_store(hv, "id", 2, newSViv(process->id), 0); + (void) hv_store(hv, "name", 4, new_pv(process->name), 0); + (void) hv_store(hv, "args", 4, new_pv(process->args), 0); - hv_store(hv, "pid", 3, newSViv(process->pid), 0); - hv_store(hv, "target", 6, new_pv(process->target), 0); + (void) hv_store(hv, "pid", 3, newSViv(process->pid), 0); + (void) hv_store(hv, "target", 6, new_pv(process->target), 0); if (process->target_win != NULL) { - hv_store(hv, "target_win", 10, + (void) hv_store(hv, "target_win", 10, plain_bless(process->target_win, "Irssi::UI::Window"), 0); } - hv_store(hv, "shell", 5, newSViv(process->shell), 0); - hv_store(hv, "notice", 6, newSViv(process->notice), 0); - hv_store(hv, "silent", 6, newSViv(process->silent), 0); + (void) hv_store(hv, "shell", 5, newSViv(process->shell), 0); + (void) hv_store(hv, "notice", 6, newSViv(process->notice), 0); + (void) hv_store(hv, "silent", 6, newSViv(process->silent), 0); } static void perl_window_fill_hash(HV *hv, WINDOW_REC *window) { - hv_store(hv, "refnum", 6, newSViv(window->refnum), 0); - hv_store(hv, "name", 4, new_pv(window->name), 0); - hv_store(hv, "history_name", 12, new_pv(window->history_name), 0); + (void) hv_store(hv, "refnum", 6, newSViv(window->refnum), 0); + (void) hv_store(hv, "name", 4, new_pv(window->name), 0); + (void) hv_store(hv, "history_name", 12, new_pv(window->history_name), 0); - hv_store(hv, "width", 5, newSViv(window->width), 0); - hv_store(hv, "height", 6, newSViv(window->height), 0); + (void) hv_store(hv, "width", 5, newSViv(window->width), 0); + (void) hv_store(hv, "height", 6, newSViv(window->height), 0); if (window->active) - hv_store(hv, "active", 6, iobject_bless(window->active), 0); + (void) hv_store(hv, "active", 6, iobject_bless(window->active), 0); if (window->active_server) - hv_store(hv, "active_server", 13, iobject_bless(window->active_server), 0); + (void) hv_store(hv, "active_server", 13, iobject_bless(window->active_server), 0); - hv_store(hv, "servertag", 9, new_pv(window->servertag), 0); - hv_store(hv, "level", 5, newSViv(window->level), 0); + (void) hv_store(hv, "servertag", 9, new_pv(window->servertag), 0); + (void) hv_store(hv, "level", 5, newSViv(window->level), 0); - hv_store(hv, "immortal", 8, newSViv(window->immortal), 0); - hv_store(hv, "sticky_refnum", 13, newSViv(window->sticky_refnum), 0); + (void) hv_store(hv, "immortal", 8, newSViv(window->immortal), 0); + (void) hv_store(hv, "sticky_refnum", 13, newSViv(window->sticky_refnum), 0); - hv_store(hv, "data_level", 10, newSViv(window->data_level), 0); - hv_store(hv, "hilight_color", 13, new_pv(window->hilight_color), 0); + (void) hv_store(hv, "data_level", 10, newSViv(window->data_level), 0); + (void) hv_store(hv, "hilight_color", 13, new_pv(window->hilight_color), 0); - hv_store(hv, "last_timestamp", 14, newSViv(window->last_timestamp), 0); - hv_store(hv, "last_line", 9, newSViv(window->last_line), 0); + (void) hv_store(hv, "last_timestamp", 14, newSViv(window->last_timestamp), 0); + (void) hv_store(hv, "last_line", 9, newSViv(window->last_line), 0); - hv_store(hv, "theme", 5, plain_bless(window->theme, "Irssi::UI::Theme"), 0); - hv_store(hv, "theme_name", 10, new_pv(window->theme_name), 0); + (void) hv_store(hv, "theme", 5, plain_bless(window->theme, "Irssi::UI::Theme"), 0); + (void) hv_store(hv, "theme_name", 10, new_pv(window->theme_name), 0); } static void perl_text_dest_fill_hash(HV *hv, TEXT_DEST_REC *dest) { - hv_store(hv, "window", 6, plain_bless(dest->window, "Irssi::UI::Window"), 0); - hv_store(hv, "server", 6, iobject_bless(dest->server), 0); - hv_store(hv, "target", 6, new_pv(dest->target), 0); - hv_store(hv, "level", 5, newSViv(dest->level), 0); + (void) hv_store(hv, "window", 6, plain_bless(dest->window, "Irssi::UI::Window"), 0); + (void) hv_store(hv, "server", 6, iobject_bless(dest->server), 0); + (void) hv_store(hv, "target", 6, new_pv(dest->target), 0); + (void) hv_store(hv, "level", 5, newSViv(dest->level), 0); - hv_store(hv, "hilight_priority", 16, newSViv(dest->hilight_priority), 0); - hv_store(hv, "hilight_color", 13, new_pv(dest->hilight_color), 0); + (void) hv_store(hv, "hilight_priority", 16, newSViv(dest->hilight_priority), 0); + (void) hv_store(hv, "hilight_color", 13, new_pv(dest->hilight_color), 0); } static PLAIN_OBJECT_INIT_REC fe_plains[] = { From 96d4fb9156bcef6fc14dbec43dfa0fcd0226d46f Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Wed, 7 Jan 2015 03:40:34 +0100 Subject: [PATCH 0061/1650] add CONFIG_REC to config_node_section* APIs this adds the CONFIG_REC * to the config_node_section and config_node_section_index APIs as they will require access to the config cache later on to make the config parser more robust. --- src/core/channels-setup.c | 2 +- src/core/chatnets.c | 2 +- src/core/ignore.c | 6 +++--- src/core/log.c | 8 ++++---- src/core/servers-setup.c | 2 +- src/core/session.c | 14 +++++++------- src/core/settings.c | 14 +++++++------- src/core/settings.h | 2 ++ src/fe-common/core/completion.c | 4 ++-- src/fe-common/core/hilight-text.c | 6 +++--- src/fe-common/core/keyboard.c | 2 +- src/fe-common/core/themes.c | 4 ++-- src/fe-common/core/windows-layout.c | 8 ++++---- src/fe-text/mainwindows-layout.c | 2 +- src/fe-text/statusbar-config.c | 20 ++++++++++---------- src/irc/core/irc-session.c | 4 ++-- src/irc/notifylist/notify-setup.c | 6 +++--- src/lib-config/get.c | 8 ++++---- src/lib-config/iconfig.h | 4 ++-- src/lib-config/parse.c | 4 ++-- 20 files changed, 62 insertions(+), 60 deletions(-) diff --git a/src/core/channels-setup.c b/src/core/channels-setup.c index e1289c23..b2d971dd 100644 --- a/src/core/channels-setup.c +++ b/src/core/channels-setup.c @@ -40,7 +40,7 @@ static void channel_setup_save(CHANNEL_SETUP_REC *channel) parentnode = iconfig_node_traverse("(channels", TRUE); node = config_node_nth(parentnode, index); if (node == NULL) - node = config_node_section(parentnode, NULL, NODE_TYPE_BLOCK); + node = iconfig_node_section(parentnode, NULL, NODE_TYPE_BLOCK); iconfig_node_clear(node); iconfig_node_set_str(node, "name", channel->name); diff --git a/src/core/chatnets.c b/src/core/chatnets.c index 3c794ab4..dd4d94b3 100644 --- a/src/core/chatnets.c +++ b/src/core/chatnets.c @@ -36,7 +36,7 @@ static void chatnet_config_save(CHATNET_REC *chatnet) CONFIG_NODE *node; node = iconfig_node_traverse("chatnets", TRUE); - node = config_node_section(node, chatnet->name, NODE_TYPE_BLOCK); + node = iconfig_node_section(node, chatnet->name, NODE_TYPE_BLOCK); iconfig_node_clear(node); iconfig_node_set_str(node, "type", chat_protocol_find_id(chatnet->chat_type)->name); diff --git a/src/core/ignore.c b/src/core/ignore.c index 68fae11f..2d18f865 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -263,7 +263,7 @@ static void ignore_set_config(IGNORE_REC *rec) return; node = iconfig_node_traverse("(ignores", TRUE); - node = config_node_section(node, NULL, NODE_TYPE_BLOCK); + node = iconfig_node_section(node, NULL, NODE_TYPE_BLOCK); if (rec->mask != NULL) iconfig_node_set_str(node, "mask", rec->mask); if (rec->level) { @@ -281,7 +281,7 @@ static void ignore_set_config(IGNORE_REC *rec) iconfig_node_set_str(node, "servertag", rec->servertag); if (rec->channels != NULL && *rec->channels != NULL) { - node = config_node_section(node, "channels", NODE_TYPE_LIST); + node = iconfig_node_section(node, "channels", NODE_TYPE_LIST); iconfig_node_add_list(node, rec->channels); } } @@ -436,7 +436,7 @@ static void read_ignores(void) rec->unignore_time = config_node_get_int(node, "unignore_time", 0); rec->servertag = g_strdup(config_node_get_str(node, "servertag", 0)); - node = config_node_section(node, "channels", -1); + node = iconfig_node_section(node, "channels", -1); if (node != NULL) rec->channels = config_node_get_list(node); ignore_init_rec(rec); diff --git a/src/core/log.c b/src/core/log.c index d4d3853e..c9732d6d 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -332,11 +332,11 @@ static void log_items_update_config(LOG_REC *log, CONFIG_NODE *parent) GSList *tmp; CONFIG_NODE *node; - parent = config_node_section(parent, "items", NODE_TYPE_LIST); + parent = iconfig_node_section(parent, "items", NODE_TYPE_LIST); for (tmp = log->items; tmp != NULL; tmp = tmp->next) { LOG_ITEM_REC *rec = tmp->data; - node = config_node_section(parent, NULL, NODE_TYPE_BLOCK); + node = iconfig_node_section(parent, NULL, NODE_TYPE_BLOCK); iconfig_node_set_str(node, "type", log_item_types[rec->type]); iconfig_node_set_str(node, "name", rec->name); iconfig_node_set_str(node, "server", rec->servertag); @@ -352,7 +352,7 @@ static void log_update_config(LOG_REC *log) return; node = iconfig_node_traverse("logs", TRUE); - node = config_node_section(node, log->fname, NODE_TYPE_BLOCK); + node = iconfig_node_section(node, log->fname, NODE_TYPE_BLOCK); if (log->autoopen) iconfig_node_set_bool(node, "auto_open", TRUE); @@ -544,7 +544,7 @@ static void log_read_config(void) signal_emit("log config read", 2, log, node); - node = config_node_section(node, "items", -1); + node = iconfig_node_section(node, "items", -1); if (node != NULL) log_items_read_config(node, log); diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 27d9f1f0..e648eb36 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -430,7 +430,7 @@ static void server_setup_save(SERVER_SETUP_REC *rec) parentnode = iconfig_node_traverse("(servers", TRUE); node = config_node_nth(parentnode, index); if (node == NULL) - node = config_node_section(parentnode, NULL, NODE_TYPE_BLOCK); + node = iconfig_node_section(parentnode, NULL, NODE_TYPE_BLOCK); iconfig_node_clear(node); iconfig_node_set_str(node, "address", rec->address); diff --git a/src/core/session.c b/src/core/session.c index b3002632..ca3bf22f 100644 --- a/src/core/session.c +++ b/src/core/session.c @@ -92,7 +92,7 @@ static void cmd_upgrade(const char *data) static void session_save_nick(CHANNEL_REC *channel, NICK_REC *nick, CONFIG_REC *config, CONFIG_NODE *node) { - node = config_node_section(node, NULL, NODE_TYPE_BLOCK); + node = config_node_section(config, node, NULL, NODE_TYPE_BLOCK); config_node_set_str(config, node, "nick", nick->nick); config_node_set_bool(config, node, "op", nick->op); @@ -109,7 +109,7 @@ static void session_save_channel_nicks(CHANNEL_REC *channel, CONFIG_REC *config, { GSList *tmp, *nicks; - node = config_node_section(node, "nicks", NODE_TYPE_LIST); + node = config_node_section(config, node, "nicks", NODE_TYPE_LIST); nicks = nicklist_getnicks(channel); for (tmp = nicks; tmp != NULL; tmp = tmp->next) session_save_nick(channel, tmp->data, config, node); @@ -119,7 +119,7 @@ static void session_save_channel_nicks(CHANNEL_REC *channel, CONFIG_REC *config, static void session_save_channel(CHANNEL_REC *channel, CONFIG_REC *config, CONFIG_NODE *node) { - node = config_node_section(node, NULL, NODE_TYPE_BLOCK); + node = config_node_section(config, node, NULL, NODE_TYPE_BLOCK); config_node_set_str(config, node, "name", channel->name); config_node_set_str(config, node, "visible_name", channel->visible_name); @@ -138,7 +138,7 @@ static void session_save_server_channels(SERVER_REC *server, GSList *tmp; /* save channels */ - node = config_node_section(node, "channels", NODE_TYPE_LIST); + node = config_node_section(config, node, "channels", NODE_TYPE_LIST); for (tmp = server->channels; tmp != NULL; tmp = tmp->next) session_save_channel(tmp->data, config, node); } @@ -148,7 +148,7 @@ static void session_save_server(SERVER_REC *server, CONFIG_REC *config, { int handle; - node = config_node_section(node, NULL, NODE_TYPE_BLOCK); + node = config_node_section(config, node, NULL, NODE_TYPE_BLOCK); config_node_set_str(config, node, "chat_type", chat_protocol_find_id(server->chat_type)->name); @@ -187,7 +187,7 @@ static void session_restore_channel_nicks(CHANNEL_REC *channel, GSList *tmp; /* restore nicks */ - node = config_node_section(node, "nicks", -1); + node = config_node_section(NULL, node, "nicks", -1); if (node != NULL && node->type == NODE_TYPE_LIST) { tmp = config_node_first(node->value); for (; tmp != NULL; tmp = config_node_next(tmp)) { @@ -223,7 +223,7 @@ static void session_restore_server_channels(SERVER_REC *server, GSList *tmp; /* restore channels */ - node = config_node_section(node, "channels", -1); + node = config_node_section(NULL, node, "channels", -1); if (node != NULL && node->type == NODE_TYPE_LIST) { tmp = config_node_first(node->value); for (; tmp != NULL; tmp = config_node_next(tmp)) diff --git a/src/core/settings.c b/src/core/settings.c index 2296909e..6c536180 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -77,7 +77,7 @@ settings_get_str_type(const char *key, SettingType type) if (rec == NULL) return NULL; node = iconfig_node_traverse("settings", FALSE); - node = node == NULL ? NULL : config_node_section(node, rec->module, -1); + node = node == NULL ? NULL : iconfig_node_section(node, rec->module, -1); return node == NULL ? rec->default_value.v_string : config_node_get_str(node, key, rec->default_value.v_string); @@ -97,7 +97,7 @@ int settings_get_int(const char *key) if (rec == NULL) return 0; node = iconfig_node_traverse("settings", FALSE); - node = node == NULL ? NULL : config_node_section(node, rec->module, -1); + node = node == NULL ? NULL : iconfig_node_section(node, rec->module, -1); return node == NULL ? rec->default_value.v_int : config_node_get_int(node, key, rec->default_value.v_int); @@ -112,7 +112,7 @@ int settings_get_bool(const char *key) if (rec == NULL) return FALSE; node = iconfig_node_traverse("settings", FALSE); - node = node == NULL ? NULL : config_node_section(node, rec->module, -1); + node = node == NULL ? NULL : iconfig_node_section(node, rec->module, -1); return node == NULL ? rec->default_value.v_bool : config_node_get_bool(node, key, rec->default_value.v_bool); @@ -324,7 +324,7 @@ static CONFIG_NODE *settings_get_node(const char *key) } node = iconfig_node_traverse("settings", TRUE); - return config_node_section(node, rec->module, NODE_TYPE_BLOCK); + return iconfig_node_section(node, rec->module, NODE_TYPE_BLOCK); } void settings_set_str(const char *key, const char *value) @@ -420,7 +420,7 @@ static void settings_clean_invalid_module(const char *module) node = iconfig_node_traverse("settings", FALSE); if (node == NULL) return; - node = config_node_section(node, module, -1); + node = iconfig_node_section(node, module, -1); if (node == NULL) return; for (tmp = config_node_first(node->value); tmp != NULL; tmp = next) { @@ -468,7 +468,7 @@ static int backwards_compatibility(const char *module, CONFIG_NODE *node, g_strdup(node->value); new_node = iconfig_node_traverse("settings", FALSE); new_node = new_node == NULL ? NULL : - config_node_section(new_node, new_module, -1); + iconfig_node_section(new_node, new_module, -1); config_node_set_str(mainconfig, new_node, new_key, new_value); @@ -502,7 +502,7 @@ void settings_check_module(const char *module) g_return_if_fail(module != NULL); node = iconfig_node_traverse("settings", FALSE); - node = node == NULL ? NULL : config_node_section(node, module, -1); + node = node == NULL ? NULL : iconfig_node_section(node, module, -1); if (node == NULL) return; errors = g_string_new(NULL); diff --git a/src/core/settings.h b/src/core/settings.h index f8d9f68f..af00cc80 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -36,6 +36,8 @@ typedef struct { #define iconfig_set_int(a, b, c) config_set_int(mainconfig, a, b, c) #define iconfig_set_bool(a, b, c) config_set_bool(mainconfig, a, b, c) +#define iconfig_node_section(a, b, c) config_node_section(mainconfig, a, b, c) +#define iconfig_node_section_index(a, b, c, d) config_node_section_index(mainconfig, a, b, c, d) #define iconfig_node_traverse(a, b) config_node_traverse(mainconfig, a, b) #define iconfig_node_set_str(a, b, c) config_node_set_str(mainconfig, a, b, c) #define iconfig_node_set_int(a, b, c) config_node_set_int(mainconfig, a, b, c) diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index 31d62e10..2223b5b5 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -51,7 +51,7 @@ static const char *completion_find(const char *key, int automatic) if (node == NULL || node->type != NODE_TYPE_BLOCK) return NULL; - node = config_node_section(node, key, -1); + node = iconfig_node_section(node, key, -1); if (node == NULL) return NULL; @@ -785,7 +785,7 @@ static void cmd_completion(const char *data) } else if (*key != '\0' && *value != '\0') { int automatic = g_hash_table_lookup(optlist, "auto") != NULL; - node = config_node_section(node, key, NODE_TYPE_BLOCK); + node = iconfig_node_section(node, key, NODE_TYPE_BLOCK); iconfig_node_set_str(node, "value", value); if (automatic) iconfig_node_set_bool(node, "auto", TRUE); diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 4b914517..de9a3130 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -66,7 +66,7 @@ static void hilight_add_config(HILIGHT_REC *rec) g_return_if_fail(rec != NULL); node = iconfig_node_traverse("(hilights", TRUE); - node = config_node_section(node, NULL, NODE_TYPE_BLOCK); + 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); @@ -81,7 +81,7 @@ static void hilight_add_config(HILIGHT_REC *rec) if (rec->servertag) iconfig_node_set_str(node, "servertag", rec->servertag); if (rec->channels != NULL && *rec->channels != NULL) { - node = config_node_section(node, "channels", NODE_TYPE_LIST); + node = iconfig_node_section(node, "channels", NODE_TYPE_LIST); iconfig_node_add_list(node, rec->channels); } } @@ -471,7 +471,7 @@ static void read_hilight_config(void) rec->servertag = config_node_get_str(node, "servertag", NULL); hilight_init_rec(rec); - node = config_node_section(node, "channels", -1); + node = iconfig_node_section(node, "channels", -1); if (node != NULL) rec->channels = config_node_get_list(node); } diff --git a/src/fe-common/core/keyboard.c b/src/fe-common/core/keyboard.c index bec1502e..02c8a8d7 100644 --- a/src/fe-common/core/keyboard.c +++ b/src/fe-common/core/keyboard.c @@ -135,7 +135,7 @@ static void keyconfig_save(const char *id, const char *key, const char *data) node = key_config_find(key); if (node == NULL) { node = iconfig_node_traverse("(keyboard", TRUE); - node = config_node_section(node, NULL, NODE_TYPE_BLOCK); + node = iconfig_node_section(node, NULL, NODE_TYPE_BLOCK); } iconfig_node_set_str(node, "key", key); diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c index c0741cef..cd4039b9 100644 --- a/src/fe-common/core/themes.c +++ b/src/fe-common/core/themes.c @@ -739,7 +739,7 @@ static void theme_read_formats(THEME_REC *theme, const char *module, node = config_node_traverse(config, "formats", FALSE); if (node == NULL) return; - node = config_node_section(node, module, -1); + node = config_node_section(config, node, module, -1); if (node == NULL) return; for (tmp = node->value; tmp != NULL; tmp = tmp->next) { @@ -1177,7 +1177,7 @@ static void module_save(const char *module, MODULE_THEME_REC *rec, fnode = config_node_traverse(data->config, "formats", TRUE); - node = config_node_section(fnode, rec->name, NODE_TYPE_BLOCK); + node = config_node_section(data->config, fnode, rec->name, NODE_TYPE_BLOCK); for (n = 1; formats[n].def != NULL; n++) { if (rec->formats[n] != NULL) { config_node_set_str(data->config, node, formats[n].tag, diff --git a/src/fe-common/core/windows-layout.c b/src/fe-common/core/windows-layout.c index 54d7dcbf..d0606bc9 100644 --- a/src/fe-common/core/windows-layout.c +++ b/src/fe-common/core/windows-layout.c @@ -143,7 +143,7 @@ static void sig_layout_restore(void) if (window->theme_name != NULL) window->theme = theme_load(window->theme_name); - window_add_items(window, config_node_section(node, "items", -1)); + window_add_items(window, iconfig_node_section(node, "items", -1)); signal_emit("layout restore window", 2, window, node); } } @@ -160,7 +160,7 @@ static void sig_layout_save_item(WINDOW_REC *window, WI_ITEM_REC *item, if (type == NULL) return; - subnode = config_node_section(node, NULL, NODE_TYPE_BLOCK); + subnode = iconfig_node_section(node, NULL, NODE_TYPE_BLOCK); iconfig_node_set_str(subnode, "type", type); proto = item->chat_type == 0 ? NULL : @@ -185,7 +185,7 @@ static void window_save_items(WINDOW_REC *window, CONFIG_NODE *node) { GSList *tmp; - node = config_node_section(node, "items", NODE_TYPE_LIST); + node = iconfig_node_section(node, "items", NODE_TYPE_LIST); for (tmp = window->items; tmp != NULL; tmp = tmp->next) signal_emit("layout save item", 3, window, tmp->data, node); } @@ -195,7 +195,7 @@ static void window_save(WINDOW_REC *window, CONFIG_NODE *node) char refnum[MAX_INT_STRLEN]; ltoa(refnum, window->refnum); - node = config_node_section(node, refnum, NODE_TYPE_BLOCK); + node = iconfig_node_section(node, refnum, NODE_TYPE_BLOCK); if (window->sticky_refnum) iconfig_node_set_bool(node, "sticky_refnum", TRUE); diff --git a/src/fe-text/mainwindows-layout.c b/src/fe-text/mainwindows-layout.c index 28fae924..c53f8f72 100644 --- a/src/fe-text/mainwindows-layout.c +++ b/src/fe-text/mainwindows-layout.c @@ -70,7 +70,7 @@ static void main_window_save(MAIN_WINDOW_REC *window, CONFIG_NODE *node) char num[MAX_INT_STRLEN]; ltoa(num, window->active->refnum); - node = config_node_section(node, num, NODE_TYPE_BLOCK); + node = iconfig_node_section(node, num, NODE_TYPE_BLOCK); iconfig_node_set_int(node, "first_line", window->first_line); iconfig_node_set_int(node, "lines", window->height); diff --git a/src/fe-text/statusbar-config.c b/src/fe-text/statusbar-config.c index deaa1b5d..e8943dac 100644 --- a/src/fe-text/statusbar-config.c +++ b/src/fe-text/statusbar-config.c @@ -177,7 +177,7 @@ static void statusbar_read(STATUSBAR_GROUP_REC *group, CONFIG_NODE *node) bar->placement = STATUSBAR_TOP; bar->position = config_node_get_int(node, "position", 0); - node = config_node_section(node, "items", -1); + node = iconfig_node_section(node, "items", -1); if (node != NULL) { /* we're overriding the items - destroy the old */ while (bar->items != NULL) @@ -227,7 +227,7 @@ static void read_statusbar_config_from_node(CONFIG_NODE *node) CONFIG_NODE *items; GSList *tmp; - items = config_node_section(node, "items", -1); + items = iconfig_node_section(node, "items", -1); if (items != NULL) statusbar_read_items(items); @@ -369,7 +369,7 @@ static void cmd_statusbar_reset(const char *data, void *server, CONFIG_NODE *parent; parent = iconfig_node_traverse("statusbar", TRUE); - parent = config_node_section(parent, active_statusbar_group->name, + parent = iconfig_node_section(parent, active_statusbar_group->name, NODE_TYPE_BLOCK); iconfig_node_set_str(parent, node->key, NULL); @@ -432,7 +432,7 @@ static CONFIG_NODE *statusbar_items_section(CONFIG_NODE *parent) CONFIG_NODE *node; GSList *tmp; - node = config_node_section(parent, "items", -1); + node = iconfig_node_section(parent, "items", -1); if (node != NULL) return node; @@ -446,11 +446,11 @@ static CONFIG_NODE *statusbar_items_section(CONFIG_NODE *parent) /* since items list in config file overrides defaults, we'll need to copy the whole list. */ - parent = config_node_section(parent, "items", NODE_TYPE_BLOCK); + parent = iconfig_node_section(parent, "items", NODE_TYPE_BLOCK); for (tmp = bar->items; tmp != NULL; tmp = tmp->next) { SBAR_ITEM_CONFIG_REC *rec = tmp->data; - node = config_node_section(parent, rec->name, + node = iconfig_node_section(parent, rec->name, NODE_TYPE_BLOCK); if (rec->priority != 0) iconfig_node_set_int(node, "priority", rec->priority); @@ -487,7 +487,7 @@ static void cmd_statusbar_add(const char *data, void *server, if (value != NULL) index = config_node_index(node, value)+1; /* create/move item */ - node = config_node_section_index(node, name, index, NODE_TYPE_BLOCK); + node = iconfig_node_section_index(node, name, index, NODE_TYPE_BLOCK); /* set the options */ value = g_hash_table_lookup(optlist, "priority"); @@ -511,7 +511,7 @@ static void cmd_statusbar_remove(const char *data, void *server, if (node == NULL) return; - if (config_node_section(node, data, -1) != NULL) + if (iconfig_node_section(node, data, -1) != NULL) iconfig_node_set_str(node, data, NULL); else { printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, @@ -545,9 +545,9 @@ static void cmd_statusbar(const char *data) /* lookup/create the statusbar node */ node = iconfig_node_traverse("statusbar", TRUE); - node = config_node_section(node, active_statusbar_group->name, + node = iconfig_node_section(node, active_statusbar_group->name, NODE_TYPE_BLOCK); - node = config_node_section(node, name, NODE_TYPE_BLOCK); + node = iconfig_node_section(node, name, NODE_TYPE_BLOCK); /* call the subcommand */ signal = g_strconcat("command statusbar ", cmd, NULL); diff --git a/src/irc/core/irc-session.c b/src/irc/core/irc-session.c index 42d82734..ea65d8a5 100644 --- a/src/irc/core/irc-session.c +++ b/src/irc/core/irc-session.c @@ -66,7 +66,7 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config, config_node_set_bool(config, node, "emode_known", server->emode_known); config_node_set_bool(config, node, "isupport_sent", server->isupport_sent); - isupport = config_node_section(node, "isupport", NODE_TYPE_BLOCK); + isupport = config_node_section(config, node, "isupport", NODE_TYPE_BLOCK); isupport_data.config = config; isupport_data.node = isupport; @@ -95,7 +95,7 @@ static void sig_session_restore_server(IRC_SERVER_REC *server, (GCompareFunc) g_istr_equal); } - node = config_node_section(node, "isupport", -1); + node = config_node_section(NULL, node, "isupport", -1); tmp = node == NULL ? NULL : config_node_first(node->value); for (; tmp != NULL; tmp = config_node_next(tmp)) { diff --git a/src/irc/notifylist/notify-setup.c b/src/irc/notifylist/notify-setup.c index d6f91361..9ea481ca 100644 --- a/src/irc/notifylist/notify-setup.c +++ b/src/irc/notifylist/notify-setup.c @@ -30,7 +30,7 @@ void notifylist_add_config(NOTIFYLIST_REC *rec) CONFIG_NODE *node; node = iconfig_node_traverse("notifies", TRUE); - node = config_node_section(node, rec->mask, NODE_TYPE_BLOCK); + node = iconfig_node_section(node, rec->mask, NODE_TYPE_BLOCK); if (rec->away_check) iconfig_node_set_bool(node, "away_check", TRUE); @@ -39,7 +39,7 @@ void notifylist_add_config(NOTIFYLIST_REC *rec) iconfig_node_set_str(node, "ircnets", NULL); if (rec->ircnets != NULL && *rec->ircnets != NULL) { - node = config_node_section(node, "ircnets", NODE_TYPE_LIST); + node = iconfig_node_section(node, "ircnets", NODE_TYPE_LIST); iconfig_node_add_list(node, rec->ircnets); } } @@ -73,7 +73,7 @@ void notifylist_read_config(void) rec->mask = g_strdup(node->key); rec->away_check = config_node_get_bool(node, "away_check", FALSE); - node = config_node_section(node, "ircnets", -1); + node = iconfig_node_section(node, "ircnets", -1); if (node != NULL) rec->ircnets = config_node_get_list(node); } } diff --git a/src/lib-config/get.c b/src/lib-config/get.c index af02b048..52785f63 100644 --- a/src/lib-config/get.c +++ b/src/lib-config/get.c @@ -38,12 +38,12 @@ CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key) return NULL; } -CONFIG_NODE *config_node_section(CONFIG_NODE *parent, const char *key, int new_type) +CONFIG_NODE *config_node_section(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int new_type) { - return config_node_section_index(parent, key, -1, new_type); + return config_node_section_index(rec, parent, key, -1, new_type); } -CONFIG_NODE *config_node_section_index(CONFIG_NODE *parent, const char *key, +CONFIG_NODE *config_node_section_index(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int index, int new_type) { CONFIG_NODE *node; @@ -101,7 +101,7 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea is_list = **tmp == '('; if (create) new_type = is_list ? NODE_TYPE_LIST : NODE_TYPE_BLOCK; - node = config_node_section(node, *tmp + is_list, new_type); + node = config_node_section(rec, node, *tmp + is_list, new_type); if (node == NULL) { g_strfreev(list); return NULL; diff --git a/src/lib-config/iconfig.h b/src/lib-config/iconfig.h index 3d9eb931..91583e40 100644 --- a/src/lib-config/iconfig.h +++ b/src/lib-config/iconfig.h @@ -116,8 +116,8 @@ int config_set_bool(CONFIG_REC *rec, const char *section, const char *key, int v CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key); /* Find the section from node - if not found create it unless new_type is -1. You can also specify in new_type if it's NODE_TYPE_LIST or NODE_TYPE_BLOCK */ -CONFIG_NODE *config_node_section(CONFIG_NODE *parent, const char *key, int new_type); -CONFIG_NODE *config_node_section_index(CONFIG_NODE *parent, const char *key, +CONFIG_NODE *config_node_section(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int new_type); +CONFIG_NODE *config_node_section_index(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int index, int new_type); /* Find the section with the whole path. Create the path if necessary if `create' is TRUE. */ diff --git a/src/lib-config/parse.c b/src/lib-config/parse.c index 1b20195a..c106fc46 100644 --- a/src/lib-config/parse.c +++ b/src/lib-config/parse.c @@ -173,7 +173,7 @@ static GTokenType config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node) if (key == NULL && node->type != NODE_TYPE_LIST) return G_TOKEN_ERROR; - newnode = config_node_section(node, key, NODE_TYPE_BLOCK); + newnode = config_node_section(rec, node, key, NODE_TYPE_BLOCK); config_parse_loop(rec, newnode, (GTokenType) '}'); g_free_not_null(key); @@ -188,7 +188,7 @@ static GTokenType config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node) /* list */ if (key == NULL) return G_TOKEN_ERROR; - newnode = config_node_section(node, key, NODE_TYPE_LIST); + newnode = config_node_section(rec, node, key, NODE_TYPE_LIST); config_parse_loop(rec, newnode, (GTokenType) ')'); g_free_not_null(key); From af6b789d2a6cadce0b8050f9233cacb1d0595913 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Tue, 17 Feb 2015 09:41:26 +0100 Subject: [PATCH 0062/1650] Warn the user instead of crashing on wrong config The change introduced in #191 will crash irssi immediately if you accidentally try to /reload certain broken config files. It is enough to warn the user in this case, so we turn g_error into g_critical. --- src/lib-config/get.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib-config/get.c b/src/lib-config/get.c index 52785f63..e0d988d0 100644 --- a/src/lib-config/get.c +++ b/src/lib-config/get.c @@ -109,9 +109,9 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea } g_strfreev(list); - if (!is_node_list(node)) { + if (!is_node_list(node)) { /* Will die. Better to not corrupt the config further in this case. */ - g_error("Attempt to use non-list node as list. Corrupt config?"); + g_critical("Attempt to use non-list node `%s' as list. Corrupt config?", section); return NULL; } From 1e4f7e63249b0300cac27e725e14a0134260a387 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Tue, 17 Feb 2015 09:44:33 +0100 Subject: [PATCH 0063/1650] Refuse to load broken configs on irssi start By temporarily raising the fatal log level to critical during irssi start-up, we make it fail when the config file is broken. This is then re-set so that /reload of a broken config file will not crash irssi and just report the errors and gracefully continue instead. --- src/fe-text/irssi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index 77033d7a..6d5b9b13 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -310,6 +310,7 @@ int main(int argc, char **argv) { "version", 'v', 0, G_OPTION_ARG_NONE, &version, "Display irssi version", NULL }, { NULL } }; + int loglev; #ifdef USE_GC g_mem_set_vtable(&gc_mem_table); @@ -352,6 +353,7 @@ int main(int argc, char **argv) you have to call setlocale(LC_ALL, "") */ setlocale(LC_ALL, ""); + loglev = g_log_set_always_fatal(G_LOG_FATAL_MASK | G_LOG_LEVEL_CRITICAL); textui_init(); if (!dummy && !term_init()) { @@ -360,6 +362,7 @@ int main(int argc, char **argv) return 1; } + g_log_set_always_fatal(loglev); textui_finish_init(); main_loop = g_main_new(TRUE); From fef25d6a35d23f885937b087ed7642b327279df5 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Tue, 17 Feb 2015 09:46:52 +0100 Subject: [PATCH 0064/1650] Make the config parser more robust We add some additional checks into the config parser's node_section_index, node_traverse and node_set_str functions. In particular, we check if the requested node is of scalar or complex type and whether this matches the value found in the config. If it does not match, then a warning is issued appropriately and the config is corrected. --- src/lib-config/get.c | 48 ++++++++++++++++++++++++++++++++++++++++---- src/lib-config/set.c | 6 ++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/lib-config/get.c b/src/lib-config/get.c index e0d988d0..53d744da 100644 --- a/src/lib-config/get.c +++ b/src/lib-config/get.c @@ -54,7 +54,6 @@ CONFIG_NODE *config_node_section_index(CONFIG_REC *rec, CONFIG_NODE *parent, con node = key == NULL ? NULL : config_node_find(parent, key); if (node != NULL) { - g_return_val_if_fail(new_type == -1 || new_type == node->type, NULL); nindex = g_slist_index(parent->value, node); if (index >= 0 && nindex != index && nindex <= g_slist_length(parent->value)) { @@ -62,7 +61,25 @@ CONFIG_NODE *config_node_section_index(CONFIG_REC *rec, CONFIG_NODE *parent, con parent->value = g_slist_remove(parent->value, node); parent->value = g_slist_insert(parent->value, node, index); } - return node; + if (!is_node_list(node)) { + int show_error = 0; + + if (new_type != -1) { + config_node_remove(rec, parent, node); + node = NULL; + show_error = 1; + } else if (!g_hash_table_contains(rec->cache_nodes, node)) { + g_hash_table_insert(rec->cache_nodes, node, NULL); + show_error = 1; + } + if (show_error) + g_critical("Expected %s node at `..%s/%s' was of scalar type. Corrupt config?", + new_type == NODE_TYPE_LIST ? "list" : new_type == NODE_TYPE_BLOCK ? "block" : "section", + parent->key, key); + } else { + g_return_val_if_fail(new_type == -1 || new_type == node->type, NULL); + return node; + } } if (new_type == -1) @@ -91,7 +108,21 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea /* check if it already exists in cache */ node = g_hash_table_lookup(rec->cache, section); - if (node != NULL) return node; + if (node != NULL) { + if (create) { + const char *path = strrchr(section, '/'); + if (path == NULL) path = section; + else path++; + new_type = *path == '(' ? NODE_TYPE_LIST : NODE_TYPE_BLOCK; + if (node->type != new_type) { + g_critical("Expected %s node at `%s' was of %s type. Corrupt config?", + new_type == NODE_TYPE_LIST ? "list" : "block", section, + node->type == NODE_TYPE_LIST ? "list" : "block"); + node->type = new_type; + } + } + return node; + } new_type = -1; @@ -99,7 +130,16 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea list = g_strsplit(section, "/", -1); for (tmp = list; *tmp != NULL; tmp++) { is_list = **tmp == '('; - if (create) new_type = is_list ? NODE_TYPE_LIST : NODE_TYPE_BLOCK; + if (create) { + CONFIG_NODE *tmpnode; + + new_type = is_list ? NODE_TYPE_LIST : NODE_TYPE_BLOCK; + tmpnode = config_node_find(node, *tmp + is_list); + if (tmpnode != NULL && tmpnode->type != new_type) { + g_critical("Expected %s node at `%s' was of scalar type. Corrupt config?", is_list ? "list" : "block", section); + config_node_remove(rec, node, tmpnode); + } + } node = config_node_section(rec, node, *tmp + is_list, new_type); if (node == NULL) { diff --git a/src/lib-config/set.c b/src/lib-config/set.c index 61a101fb..5c187035 100644 --- a/src/lib-config/set.c +++ b/src/lib-config/set.c @@ -104,6 +104,12 @@ void config_node_set_str(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, return; } + if (node != NULL && !has_node_value(node)) { + g_critical("Expected scalar node at `..%s/%s' was of complex type. Corrupt config?", + parent->key, key); + config_node_remove(rec, parent, node); + node = NULL; + } if (node != NULL) { if (strcmp(node->value, value) == 0) return; From ee3eaa5428c7a574ad3d34602230f3168f204414 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Wed, 7 Jan 2015 04:12:55 +0100 Subject: [PATCH 0065/1650] fix crash in layout code when encountering wrong config --- src/fe-common/core/windows-layout.c | 1 + src/fe-text/mainwindows-layout.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/fe-common/core/windows-layout.c b/src/fe-common/core/windows-layout.c index d0606bc9..8ebcc12d 100644 --- a/src/fe-common/core/windows-layout.c +++ b/src/fe-common/core/windows-layout.c @@ -127,6 +127,7 @@ static void sig_layout_restore(void) for (; tmp != NULL; tmp = config_node_next(tmp)) { CONFIG_NODE *node = tmp->data; + if (node->key == NULL) continue; window = window_find_refnum(atoi(node->key)); if (window == NULL) window = window_create(NULL, TRUE); diff --git a/src/fe-text/mainwindows-layout.c b/src/fe-text/mainwindows-layout.c index c53f8f72..020969e6 100644 --- a/src/fe-text/mainwindows-layout.c +++ b/src/fe-text/mainwindows-layout.c @@ -179,6 +179,7 @@ static void sig_layout_restore(void) lower_window = NULL; lower_size = 0; for (i = 0, tmp = sorted_config; i < windows_count; tmp = tmp->next, i++) { CONFIG_NODE *node = tmp->data; + if (node->key == NULL) continue; /* create a new window + mainwindow */ signal_emit("gui window create override", 1, From 6ce8a64118023f79e715fc7f1e50c5ce1f4bf557 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Fri, 20 Feb 2015 14:05:58 +0100 Subject: [PATCH 0066/1650] Fix scriptassist broken on unload This is a regression introduced in c5ad61b4b0166f7cb769f23dfece2a5d4e62bd6e where one `defined' statement got removed in error while cleaning up warnings. --- scripts/scriptassist.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/scriptassist.pl b/scripts/scriptassist.pl index 12678dbb..dd6d3737 100644 --- a/scripts/scriptassist.pl +++ b/scripts/scriptassist.pl @@ -1088,7 +1088,7 @@ sub sig_command_script_load ($$$) { no strict; $script = $2 if $script =~ /(.*\/)?(.*?)\.pl$/; if ( %{ "Irssi::Script::${script}::" }) { - if ( &{ "Irssi::Script::${script}::pre_unload" }) { + if (defined &{ "Irssi::Script::${script}::pre_unload" }) { print CLIENTCRAP "%R>>%n Triggering pre_unload function of $script..."; &{ "Irssi::Script::${script}::pre_unload" }(); } From d27c54486f3e5656445b43affd37f17d1338a6ce Mon Sep 17 00:00:00 2001 From: Hans Nielsen Date: Tue, 24 Jun 2014 23:01:06 -0700 Subject: [PATCH 0067/1650] Change around connection signals in proxy module Change "proxy client connected" to "proxy client connecting" to avoid being confused by clients that have connected but not necessarily authenticated. Emit "proxy client connected" once authenticated, keeping the name for backwards compatibility. --- src/irc/proxy/listen.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 33392285..8f8ebe99 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -126,6 +126,9 @@ static void handle_client_connect_cmd(CLIENT_REC *client, /* client didn't send us PASS, kill it */ remove_client(client); } else { + signal_emit("proxy client connected", 1, client); + printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + "Proxy: Client finished connecting from %s", client->host); client->connected = TRUE; proxy_dump_data(client); } @@ -361,9 +364,9 @@ static void sig_listen(LISTEN_REC *listen) proxy_clients = g_slist_prepend(proxy_clients, rec); rec->listen->clients = g_slist_prepend(rec->listen->clients, rec); - signal_emit("proxy client connected", 1, rec); + signal_emit("proxy client connecting", 1, rec); printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, - "Proxy: Client connected from %s", rec->host); + "Proxy: Client connecting from %s", rec->host); } static void sig_incoming(IRC_SERVER_REC *server, const char *line) From aaa0f73eac88316978c65fb0f0c8b5d23d1dc100 Mon Sep 17 00:00:00 2001 From: Hans Nielsen Date: Tue, 24 Jun 2014 23:45:35 -0700 Subject: [PATCH 0068/1650] Make proxy messages include more detail and add status command --- src/irc/proxy/listen.c | 15 +++++++++------ src/irc/proxy/proxy.c | 34 ++++++++++++++++++++++++++++++++++ src/irc/proxy/proxy.h | 1 + 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 8f8ebe99..df0d7479 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -45,8 +45,8 @@ static void remove_client(CLIENT_REC *rec) rec->listen->clients = g_slist_remove(rec->listen->clients, rec); signal_emit("proxy client disconnected", 1, rec); - printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, - "Proxy: Client disconnected from %s", rec->host); + printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE, + "Proxy: Client %s:%d disconnected", rec->host, rec->port); g_free(rec->proxy_address); net_sendbuffer_destroy(rec->handle, TRUE); @@ -127,8 +127,9 @@ static void handle_client_connect_cmd(CLIENT_REC *client, remove_client(client); } else { signal_emit("proxy client connected", 1, client); - printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, - "Proxy: Client finished connecting from %s", client->host); + printtext(client->server, NULL, MSGLEVEL_CLIENTNOTICE, + "Proxy: Client %s:%d connected", + client->host, client->port); client->connected = TRUE; proxy_dump_data(client); } @@ -350,6 +351,7 @@ static void sig_listen(LISTEN_REC *listen) rec->listen = listen; rec->handle = sendbuf; rec->host = g_strdup(host); + rec->port = port; if (strcmp(listen->ircnet, "*") == 0) { rec->proxy_address = g_strdup("irc.proxy"); rec->server = servers == NULL ? NULL : IRC_SERVER(servers->data); @@ -365,8 +367,9 @@ static void sig_listen(LISTEN_REC *listen) rec->listen->clients = g_slist_prepend(rec->listen->clients, rec); signal_emit("proxy client connecting", 1, rec); - printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, - "Proxy: Client connecting from %s", rec->host); + printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE, + "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.c b/src/irc/proxy/proxy.c index c8f47bdf..75da112c 100644 --- a/src/irc/proxy/proxy.c +++ b/src/irc/proxy/proxy.c @@ -23,6 +23,37 @@ #include "settings.h" #include "levels.h" +#include "fe-common/core/printtext.h" + +static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server) +{ + GSList *tmp; + + printtext(server, NULL, MSGLEVEL_CLIENTNOTICE, + "Proxy: Currently connected clients: %d", + g_slist_length(proxy_clients)); + + for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { + CLIENT_REC *rec = tmp->data; + + printtext(server, NULL, MSGLEVEL_CLIENTNOTICE, + " %s:%d connect%s to %d (%s)", + rec->host, rec->port, + rec->connected ? "ed" : "ing", + rec->listen->port, rec->listen->ircnet); + } +} + +static void cmd_proxy(const char *data, IRC_SERVER_REC *server, void *item) +{ + if (*data == '\0') { + cmd_proxy_status(data, server); + return; + } + + command_runsub("proxy", data, server, item); +} + void irc_proxy_init(void) { settings_add_str("irssiproxy", "irssiproxy_ports", ""); @@ -43,6 +74,9 @@ void irc_proxy_init(void) "... to set them."); } + command_bind("proxy", NULL, (SIGNAL_FUNC) cmd_proxy); + command_bind("proxy status", NULL, (SIGNAL_FUNC) cmd_proxy_status); + proxy_listen_init(); settings_check(); module_register("proxy", "irc"); diff --git a/src/irc/proxy/proxy.h b/src/irc/proxy/proxy.h index 4ddc9da9..158b0675 100644 --- a/src/irc/proxy/proxy.h +++ b/src/irc/proxy/proxy.h @@ -19,6 +19,7 @@ typedef struct { typedef struct { char *nick, *host; + int port; NET_SENDBUF_REC *handle; int recv_tag; char *proxy_address; From 6a28bad81440290e799c4d4985f31bea6493f58b Mon Sep 17 00:00:00 2001 From: Hans Nielsen Date: Wed, 25 Jun 2014 22:29:05 -0700 Subject: [PATCH 0069/1650] Add boolean toggle for irssiproxy being enabled --- src/irc/proxy/listen.c | 12 ++++++++++++ src/irc/proxy/proxy.c | 22 +++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index df0d7479..a5772301 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -37,6 +37,8 @@ GSList *proxy_clients; static GString *next_line; static int ignore_next; +static int enabled = FALSE; + static void remove_client(CLIENT_REC *rec) { g_return_if_fail(rec != NULL); @@ -682,6 +684,11 @@ static void sig_dump(CLIENT_REC *client, const char *data) void proxy_listen_init(void) { + if (enabled) { + return; + } + enabled = TRUE; + next_line = g_string_new(NULL); proxy_clients = NULL; @@ -703,6 +710,11 @@ void proxy_listen_init(void) void proxy_listen_deinit(void) { + if (!enabled) { + return; + } + enabled = FALSE; + while (proxy_listens != NULL) remove_listen(proxy_listens->data); g_string_free(next_line, TRUE); diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c index 75da112c..1cc8aebe 100644 --- a/src/irc/proxy/proxy.c +++ b/src/irc/proxy/proxy.c @@ -27,6 +27,12 @@ static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server) { + if (!settings_get_bool("irssiproxy")) { + printtext(server, NULL, MSGLEVEL_CLIENTNOTICE, + "Proxy is currently disabled"); + return; + } + GSList *tmp; printtext(server, NULL, MSGLEVEL_CLIENTNOTICE, @@ -54,11 +60,21 @@ static void cmd_proxy(const char *data, IRC_SERVER_REC *server, void *item) command_runsub("proxy", data, server, item); } +static void irc_proxy_setup_changed(void) +{ + if (settings_get_bool("irssiproxy")) { + proxy_listen_init(); + } else { + proxy_listen_deinit(); + } +} + void irc_proxy_init(void) { settings_add_str("irssiproxy", "irssiproxy_ports", ""); settings_add_str("irssiproxy", "irssiproxy_password", ""); settings_add_str("irssiproxy", "irssiproxy_bind", ""); + settings_add_bool("irssiproxy", "irssiproxy", TRUE); if (*settings_get_str("irssiproxy_password") == '\0') { /* no password - bad idea! */ @@ -77,7 +93,11 @@ void irc_proxy_init(void) command_bind("proxy", NULL, (SIGNAL_FUNC) cmd_proxy); command_bind("proxy status", NULL, (SIGNAL_FUNC) cmd_proxy_status); - proxy_listen_init(); + signal_add_first("setup changed", (SIGNAL_FUNC) irc_proxy_setup_changed); + + if (settings_get_bool("irssiproxy")) { + proxy_listen_init(); + } settings_check(); module_register("proxy", "irc"); } From ee3f059e6d895cda94bee0a2df7136108012b910 Mon Sep 17 00:00:00 2001 From: Hans Nielsen Date: Wed, 25 Jun 2014 22:38:03 -0700 Subject: [PATCH 0070/1650] Update proxy documentation with changes --- docs/proxy.txt | 22 ++++++++++++++++++++++ docs/signals.txt | 1 + 2 files changed, 23 insertions(+) diff --git a/docs/proxy.txt b/docs/proxy.txt index 41875aab..759ef1dc 100644 --- a/docs/proxy.txt +++ b/docs/proxy.txt @@ -12,6 +12,11 @@ In irssi, say: /LOAD proxy +If you want the proxy to be loaded automatically at startup, add the +load command to ~/.irssi/startup: + + echo "load proxy" >> ~/.irssi/startup + You really should set some password for the proxy with: /SET irssiproxy_password secret @@ -24,3 +29,20 @@ something like: 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. + +By default, the proxy binds to all available interfaces. To make it +only listen on (for example) the loopback address: + + /SET irssiproxy_bind 127.0.0.1 + +Note that bind address changes won't take effect until the proxy is +disabled and then reenabled. + +Once everything is set up, you can enable / disable the proxy: + + /TOGGLE irssiproxy + +When the proxy is configured and running, the following command will +show all the currently connected clients: + + /PROXY status diff --git a/docs/signals.txt b/docs/signals.txt index f0860d3e..bd5849f1 100644 --- a/docs/signals.txt +++ b/docs/signals.txt @@ -220,6 +220,7 @@ notifylist.c: proxy/listen.c: + "proxy client connecting", CLIENT_REC "proxy client connected", CLIENT_REC "proxy client disconnected", CLIENT_REC "proxy client command", CLIENT_REC, char *args, char *data From 178d595c96dafe36a7041864a00e1e45375dab76 Mon Sep 17 00:00:00 2001 From: Hans Nielsen Date: Tue, 1 Jul 2014 21:21:03 -0700 Subject: [PATCH 0071/1650] Add port to proxy client struct for Perl scripts --- src/perl/irc/Irc.xs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs index 18665cb7..a245206c 100644 --- a/src/perl/irc/Irc.xs +++ b/src/perl/irc/Irc.xs @@ -149,6 +149,7 @@ 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, "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 bbf404b6112aac5cde9732d893e440d9bf363565 Mon Sep 17 00:00:00 2001 From: Hans Nielsen Date: Mon, 15 Dec 2014 18:41:45 -0800 Subject: [PATCH 0072/1650] Fix whitespace --- 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 a5772301..a1cda250 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -368,7 +368,7 @@ static void sig_listen(LISTEN_REC *listen) proxy_clients = g_slist_prepend(proxy_clients, rec); rec->listen->clients = g_slist_prepend(rec->listen->clients, rec); - signal_emit("proxy client connecting", 1, 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); From 7beffbdcc5d9ca7433f6617a652ed0b2feca3677 Mon Sep 17 00:00:00 2001 From: Hans Nielsen Date: Tue, 24 Feb 2015 19:46:59 -0800 Subject: [PATCH 0073/1650] Add help files for proxy module --- docs/help/in/proxy.in | 14 ++++++++++++++ src/irc/proxy/proxy.c | 2 ++ 2 files changed, 16 insertions(+) create mode 100644 docs/help/in/proxy.in diff --git a/docs/help/in/proxy.in b/docs/help/in/proxy.in new file mode 100644 index 00000000..2dc61f43 --- /dev/null +++ b/docs/help/in/proxy.in @@ -0,0 +1,14 @@ + +@SYNTAX:proxy@ + +%9Description:%9 + + Displays the list of clients connected to the proxy. + +%9Examples:%9 + + /PROXY + /PROXY STATUS + +%9See also:%9 LOAD PROXY, SET irssiproxy + diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c index 1cc8aebe..65c778d1 100644 --- a/src/irc/proxy/proxy.c +++ b/src/irc/proxy/proxy.c @@ -25,6 +25,7 @@ #include "fe-common/core/printtext.h" +/* SYNTAX: PROXY STATUS */ static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server) { if (!settings_get_bool("irssiproxy")) { @@ -50,6 +51,7 @@ static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server) } } +/* SYNTAX: PROXY */ static void cmd_proxy(const char *data, IRC_SERVER_REC *server, void *item) { if (*data == '\0') { From be8c3c378ad8deea40973083412be3e7a9def2c1 Mon Sep 17 00:00:00 2001 From: Dima Krasner Date: Tue, 7 Apr 2015 12:13:45 +0300 Subject: [PATCH 0074/1650] Bug fix - docdir is ignored during installation. --- docs/Makefile.am | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 5e222564..861a2ca4 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,5 +1,3 @@ -docdir = $(datadir)/doc/irssi - man_MANS = \ irssi.1 From f5331a3df5f06e8ebe389aee7c91a355d5918d7c Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Tue, 7 Apr 2015 10:26:28 +0100 Subject: [PATCH 0075/1650] Make sure NO_ACT isn't cleared when -actcolor %n is used Fixes issue #227. --- src/fe-common/core/hilight-text.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 4b914517..ff3a7085 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -337,14 +337,14 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text, old_level = dest->level; if (!nick_match || (dest->level & MSGLEVEL_HILIGHT)) { - /* update the level / hilight info */ - hilight_update_text_dest(dest, hilight); /* Remove NO_ACT, this means explicitly defined hilights will bypass * /IGNORE ... NO_ACT. * (It's still possible to use /hilight -actcolor %n to hide * hilight/beep). */ dest->level &= ~MSGLEVEL_NO_ACT; + /* update the level / hilight info */ + hilight_update_text_dest(dest, hilight); } if (nick_match) From 28aaa653cf681b7bf8500b073f74a255a6fb15eb Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 7 Apr 2015 15:01:57 -0400 Subject: [PATCH 0076/1650] Add SNI support --- src/core/network-openssl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index e16403ec..dcd857d8 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -531,6 +531,10 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ return NULL; } +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + SSL_set_tlsext_host_name(ssl, server->connrec->address); +#endif + SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); From f14199d9c15a8062b5663fa6fcdae00390473b15 Mon Sep 17 00:00:00 2001 From: dequis Date: Tue, 7 Apr 2015 22:39:05 -0300 Subject: [PATCH 0077/1650] Change all strcmp() to g_strcmp0() to handle nulls gracefully Just a string replacement (but i did check every one of them) sed -i 's/strcmp(/g_strcmp0(/g' **/*.c --- src/core/channels.c | 2 +- src/core/chat-commands.c | 8 ++--- src/core/commands.c | 2 +- src/core/ignore.c | 6 ++-- src/core/levels.c | 4 +-- src/core/log.c | 8 ++--- src/core/misc.c | 4 +-- src/core/modules-load.c | 18 +++++------ src/core/modules.c | 4 +-- src/core/nicklist.c | 2 +- src/core/servers-reconnect.c | 2 +- src/core/servers-setup.c | 2 +- src/core/settings.c | 12 ++++---- src/fe-common/core/command-history.c | 6 ++-- src/fe-common/core/completion.c | 4 +-- src/fe-common/core/fe-channels.c | 6 ++-- src/fe-common/core/fe-exec.c | 2 +- src/fe-common/core/fe-help.c | 6 ++-- src/fe-common/core/fe-ignore.c | 2 +- src/fe-common/core/fe-log.c | 4 +-- src/fe-common/core/fe-messages.c | 8 ++--- src/fe-common/core/fe-queries.c | 2 +- src/fe-common/core/fe-recode.c | 2 +- src/fe-common/core/fe-server.c | 4 +-- src/fe-common/core/fe-settings.c | 2 +- src/fe-common/core/hilight-text.c | 4 +-- src/fe-common/core/keyboard.c | 10 +++--- src/fe-common/core/themes.c | 6 ++-- src/fe-common/core/window-commands.c | 4 +-- src/fe-common/irc/dcc/fe-dcc-chat.c | 2 +- src/fe-common/irc/fe-events-numeric.c | 4 +-- src/fe-common/irc/fe-irc-commands.c | 8 ++--- src/fe-common/irc/fe-irc-messages.c | 2 +- src/fe-common/irc/fe-modes.c | 2 +- src/fe-common/irc/fe-whois.c | 6 ++-- src/fe-text/gui-readline.c | 2 +- src/fe-text/statusbar-config.c | 4 +-- src/fe-text/statusbar.c | 4 +-- src/fe-text/terminfo-core.c | 6 ++-- src/irc/core/bans.c | 4 +-- src/irc/core/channel-events.c | 2 +- src/irc/core/irc-commands.c | 20 ++++++------ src/irc/core/irc-queries.c | 6 ++-- src/irc/core/irc-servers.c | 2 +- src/irc/core/modes.c | 4 +-- src/irc/core/servers-redirect.c | 6 ++-- src/irc/dcc/dcc-autoget.c | 2 +- src/irc/dcc/dcc-chat.c | 4 +-- src/irc/dcc/dcc-get.c | 2 +- src/irc/dcc/dcc.c | 4 +-- src/irc/notifylist/notifylist.c | 2 +- src/irc/proxy/dump.c | 2 +- src/irc/proxy/listen.c | 44 +++++++++++++-------------- src/lib-config/set.c | 2 +- src/perl/perl-core.c | 6 ++-- src/perl/perl-fe.c | 2 +- src/perl/perl-signals.c | 40 ++++++++++++------------ 57 files changed, 170 insertions(+), 170 deletions(-) diff --git a/src/core/channels.c b/src/core/channels.c index 8235a4c7..9af8b844 100644 --- a/src/core/channels.c +++ b/src/core/channels.c @@ -167,7 +167,7 @@ static GSList *servers_find_chatnet_except(SERVER_REC *server) SERVER_REC *rec = tmp->data; if (server != rec && rec->connrec->chatnet != NULL && - strcmp(server->connrec->chatnet, + g_strcmp0(server->connrec->chatnet, rec->connrec->chatnet) == 0) { /* chatnets match */ list = g_slist_append(list, rec); diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 8d1ac3eb..c1d874e3 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -58,7 +58,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, return NULL; } - if (strcmp(password, "-") == 0) + if (g_strcmp0(password, "-") == 0) *password = '\0'; /* check if - option is used to specify chat protocol */ @@ -283,7 +283,7 @@ static void cmd_disconnect(const char *data, SERVER_REC *server) if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg)) return; - if (*tag != '\0' && strcmp(tag, "*") != 0) { + if (*tag != '\0' && g_strcmp0(tag, "*") != 0) { server = server_find_tag(tag); if (server == NULL) server = server_find_lookup_tag(tag); @@ -343,7 +343,7 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) origtarget = target; free_ret = FALSE; - if (strcmp(target, ",") == 0 || strcmp(target, ".") == 0) { + if (g_strcmp0(target, ",") == 0 || g_strcmp0(target, ".") == 0) { target = parse_special(&target, server, item, NULL, &free_ret, NULL, 0); if (target != NULL && *target == '\0') { @@ -355,7 +355,7 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) } if (target != NULL) { - if (strcmp(target, "*") == 0) { + if (g_strcmp0(target, "*") == 0) { /* send to active channel/query */ if (item == NULL) cmd_param_error(CMDERR_NOT_JOINED); diff --git a/src/core/commands.c b/src/core/commands.c index ed82f44e..9e451bc8 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -674,7 +674,7 @@ get_optional_channel(WI_ITEM_REC *active_item, char **data, int require_name) origtmp = tmp = g_strdup(*data); channel = cmd_get_param(&tmp); - if (strcmp(channel, "*") == 0 && !require_name) { + if (g_strcmp0(channel, "*") == 0 && !require_name) { /* "*" means active channel */ cmd_get_param(data); ret = window_item_get_target(active_item); diff --git a/src/core/ignore.c b/src/core/ignore.c index 68fae11f..beca1427 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -201,10 +201,10 @@ IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, char **chan; int ignore_servertag; - if (mask != NULL && (*mask == '\0' || strcmp(mask, "*") == 0)) + if (mask != NULL && (*mask == '\0' || g_strcmp0(mask, "*") == 0)) mask = NULL; - ignore_servertag = servertag != NULL && strcmp(servertag, "*") == 0; + ignore_servertag = servertag != NULL && g_strcmp0(servertag, "*") == 0; for (tmp = ignores; tmp != NULL; tmp = tmp->next) { IGNORE_REC *rec = tmp->data; @@ -232,7 +232,7 @@ IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, if ((channels == NULL && rec->channels == NULL)) return rec; /* no channels - ok */ - if (channels != NULL && strcmp(*channels, "*") == 0) + if (channels != NULL && g_strcmp0(*channels, "*") == 0) return rec; /* ignore channels */ if (channels == NULL || rec->channels == NULL) diff --git a/src/core/levels.c b/src/core/levels.c index 7997ba98..e623c4de 100644 --- a/src/core/levels.c +++ b/src/core/levels.c @@ -54,7 +54,7 @@ int level_get(const char *level) { int n, len, match; - if (g_ascii_strcasecmp(level, "ALL") == 0 || strcmp(level, "*") == 0) + if (g_ascii_strcasecmp(level, "ALL") == 0 || g_strcmp0(level, "*") == 0) return MSGLEVEL_ALL; if (g_ascii_strcasecmp(level, "NEVER") == 0) @@ -177,7 +177,7 @@ int combine_level(int dest, const char *src) itemname = *item + (**item == '+' || **item == '-' ? 1 : 0); itemlevel = level_get(itemname); - if (strcmp(itemname, "NONE") == 0) + if (g_strcmp0(itemname, "NONE") == 0) dest = 0; else if (**item == '-') dest &= ~(itemlevel); diff --git a/src/core/log.c b/src/core/log.c index d4d3853e..35e42544 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -110,7 +110,7 @@ int log_start_logging(LOG_REC *log) log->real_fname = log_filename(log); if (log->real_fname != NULL && - strcmp(log->real_fname, log->fname) != 0) { + g_strcmp0(log->real_fname, log->fname) != 0) { /* path may contain variables (%time, $vars), make sure the directory is created */ dir = g_path_get_dirname(log->real_fname); @@ -181,7 +181,7 @@ static void log_rotate_check(LOG_REC *log) return; new_fname = log_filename(log); - if (strcmp(new_fname, log->real_fname) != 0) { + if (g_strcmp0(new_fname, log->real_fname) != 0) { /* rotate log */ log_stop_logging(log); signal_emit("log rotated", 1, log); @@ -245,7 +245,7 @@ static int itemcmp(const char *patt, const char *item) { /* returns 0 on match, nonzero otherwise */ - if (!strcmp(patt, "*")) + if (!g_strcmp0(patt, "*")) return 0; return item ? g_ascii_strcasecmp(patt, item) : 1; } @@ -320,7 +320,7 @@ LOG_REC *log_find(const char *fname) for (tmp = logs; tmp != NULL; tmp = tmp->next) { LOG_REC *rec = tmp->data; - if (strcmp(rec->fname, fname) == 0) + if (g_strcmp0(rec->fname, fname) == 0) return rec; } diff --git a/src/core/misc.c b/src/core/misc.c index 586e4f7c..ef8501d5 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -184,7 +184,7 @@ int strarray_find(char **array, const char *item) GSList *gslist_find_string(GSList *list, const char *key) { for (; list != NULL; list = list->next) - if (strcmp(list->data, key) == 0) return list; + if (g_strcmp0(list->data, key) == 0) return list; return NULL; } @@ -269,7 +269,7 @@ GSList *hashtable_get_keys(GHashTable *hash) GList *glist_find_string(GList *list, const char *key) { for (; list != NULL; list = list->next) - if (strcmp(list->data, key) == 0) return list; + if (g_strcmp0(list->data, key) == 0) return list; return NULL; } diff --git a/src/core/modules-load.c b/src/core/modules-load.c index 49f811de..6086d9ae 100644 --- a/src/core/modules-load.c +++ b/src/core/modules-load.c @@ -78,7 +78,7 @@ static char *module_get_root(const char *name, char **prefixes) /* skip the _core part */ len = strlen(name); - if (len > 5 && strcmp(name+len-5, "_core") == 0) + if (len > 5 && g_strcmp0(name+len-5, "_core") == 0) return g_strndup(name, len-5); return g_strdup(name); @@ -94,11 +94,11 @@ static char *module_get_sub(const char *name, const char *root) g_return_val_if_fail(namelen >= rootlen, g_strdup(name)); if (strncmp(name, root, rootlen) == 0 && - strcmp(name+rootlen, "_core") == 0) + g_strcmp0(name+rootlen, "_core") == 0) return g_strdup("core"); if (namelen > rootlen && name[namelen-rootlen-1] == '_' && - strcmp(name+namelen-rootlen, root) == 0) + g_strcmp0(name+namelen-rootlen, root) == 0) return g_strndup(name, namelen-rootlen-1); return g_strdup(name); @@ -140,10 +140,10 @@ static GModule *module_open(const char *name, int *found) static char *module_get_func(const char *rootmodule, const char *submodule, const char *function) { - if (strcmp(submodule, "core") == 0) + if (g_strcmp0(submodule, "core") == 0) return g_strconcat(rootmodule, "_core_", function, NULL); - if (strcmp(rootmodule, submodule) == 0) + if (g_strcmp0(rootmodule, submodule) == 0) return g_strconcat(rootmodule, "_", function, NULL); return g_strconcat(submodule, "_", rootmodule, "_", function, NULL); @@ -200,7 +200,7 @@ static int module_load_name(const char *path, const char *rootmodule, module = module_find(rootmodule); rec = module == NULL ? NULL : - strcmp(rootmodule, submodule) == 0 ? + g_strcmp0(rootmodule, submodule) == 0 ? module_file_find(module, "core") : module_file_find(module, submodule); if (rec == NULL) { @@ -277,7 +277,7 @@ static int module_load_full(const char *path, const char *rootmodule, return FALSE; module = module_find(rootmodule); - if (module != NULL && (strcmp(submodule, rootmodule) == 0 || + if (module != NULL && (g_strcmp0(submodule, rootmodule) == 0 || module_file_find(module, submodule) != NULL)) { /* module is already loaded */ module_error(MODULE_ERROR_ALREADY_LOADED, NULL, @@ -286,7 +286,7 @@ static int module_load_full(const char *path, const char *rootmodule, } /* check if the given module exists.. */ - try_prefixes = strcmp(rootmodule, submodule) == 0; + try_prefixes = g_strcmp0(rootmodule, submodule) == 0; status = module_load_name(path, rootmodule, submodule, try_prefixes); if (status == -1 && try_prefixes) { /* nope, try loading the module_core, @@ -340,7 +340,7 @@ int module_load_sub(const char *path, const char *submodule, char **prefixes) g_free(name); full_path = g_string_new(exppath); - if (strcmp(submodule, "core") == 0) + if (g_strcmp0(submodule, "core") == 0) g_string_insert(full_path, end, "_core"); else { g_string_insert_c(full_path, start, '_'); diff --git a/src/core/modules.c b/src/core/modules.c index b002819b..a2542c84 100644 --- a/src/core/modules.c +++ b/src/core/modules.c @@ -44,7 +44,7 @@ void *module_check_cast_module(void *object, int type_pos, str = module_find_id_str(module, G_STRUCT_MEMBER(int, object, type_pos)); - return str == NULL || strcmp(str, id) != 0 ? NULL : object; + return str == NULL || g_strcmp0(str, id) != 0 ? NULL : object; } /* return unique number across all modules for `id' */ @@ -251,7 +251,7 @@ MODULE_FILE_REC *module_file_find(MODULE_REC *module, const char *name) for (tmp = module->files; tmp != NULL; tmp = tmp->next) { MODULE_FILE_REC *rec = tmp->data; - if (strcmp(rec->name, name) == 0) + if (g_strcmp0(rec->name, name) == 0) return rec; } diff --git a/src/core/nicklist.c b/src/core/nicklist.c index b1c9ecef..a96b8a9e 100644 --- a/src/core/nicklist.c +++ b/src/core/nicklist.c @@ -478,7 +478,7 @@ static NICK_REC *nick_nfind(CHANNEL_REC *channel, const char *nick, int len) if (rec != NULL) { /* if there's multiple, get the one with identical case */ while (rec->next != NULL) { - if (strcmp(rec->nick, tmpnick) == 0) + if (g_strcmp0(rec->nick, tmpnick) == 0) break; rec = rec->next; } diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index d99a5405..d7660110 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -384,7 +384,7 @@ static void cmd_reconnect(const char *data, SERVER_REC *server) if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg)) return; - if (*tag != '\0' && strcmp(tag, "*") != 0) + if (*tag != '\0' && g_strcmp0(tag, "*") != 0) server = server_find_tag(tag); if (server != NULL) { diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 27d9f1f0..85aae0e2 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -526,7 +526,7 @@ static void read_servers(void) static void read_settings(void) { if (old_source_host == NULL || - strcmp(old_source_host, settings_get_str("hostname")) != 0) { + g_strcmp0(old_source_host, settings_get_str("hostname")) != 0) { g_free_not_null(old_source_host); old_source_host = g_strdup(settings_get_str("hostname")); diff --git a/src/core/settings.c b/src/core/settings.c index 2296909e..2c43fd10 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -295,7 +295,7 @@ void settings_remove(const char *key) static int settings_remove_hash(const char *key, SETTINGS_REC *rec, const char *module) { - if (strcmp(rec->module, module) == 0) { + if (g_strcmp0(rec->module, module) == 0) { settings_unref(rec, FALSE); return TRUE; } @@ -428,7 +428,7 @@ static void settings_clean_invalid_module(const char *module) next = config_node_next(tmp); set = g_hash_table_lookup(settings, subnode->key); - if (set == NULL || strcmp(set->module, module) != 0) + if (set == NULL || g_strcmp0(set->module, module) != 0) iconfig_node_remove(node, subnode); } } @@ -458,7 +458,7 @@ static int backwards_compatibility(const char *module, CONFIG_NODE *node, new_value = NULL; new_key = NULL; new_module = NULL; /* fe-text term_type -> fe-common/core term_charset - for 0.8.10-> */ - if (strcmp(module, "fe-text") == 0) { + if (g_strcmp0(module, "fe-text") == 0) { if (g_ascii_strcasecmp(node->key, "term_type") == 0 || /* kludge for cvs-version where term_charset was in fe-text */ g_ascii_strcasecmp(node->key, "term_charset") == 0) { @@ -520,7 +520,7 @@ void settings_check_module(const char *module) if (backwards_compatibility(module, node, parent)) continue; - if (set == NULL || strcmp(set->module, module) != 0) { + if (set == NULL || g_strcmp0(set->module, module) != 0) { g_string_append_printf(errors, " %s", node->key); count++; } @@ -548,9 +548,9 @@ void settings_check_module(const char *module) static int settings_compare(SETTINGS_REC *v1, SETTINGS_REC *v2) { - int cmp = strcmp(v1->section, v2->section); + int cmp = g_strcmp0(v1->section, v2->section); if (!cmp) - cmp = strcmp(v1->key, v2->key); + cmp = g_strcmp0(v1->key, v2->key); return cmp; } diff --git a/src/fe-common/core/command-history.c b/src/fe-common/core/command-history.c index 37405c43..f9c3884c 100644 --- a/src/fe-common/core/command-history.c +++ b/src/fe-common/core/command-history.c @@ -42,7 +42,7 @@ void command_history_add(HISTORY_REC *history, const char *text) g_return_if_fail(text != NULL); link = g_list_last(history->list); - if (link != NULL && strcmp(link->data, text) == 0) + if (link != NULL && g_strcmp0(link->data, text) == 0) return; /* same as previous entry */ if (settings_get_int("max_command_history") < 1 || @@ -121,7 +121,7 @@ const char *command_history_prev(WINDOW_REC *window, const char *text) } if (*text != '\0' && - (pos == NULL || strcmp(pos->data, text) != 0)) { + (pos == NULL || g_strcmp0(pos->data, text) != 0)) { /* save the old entry to history */ command_history_add(history, text); } @@ -145,7 +145,7 @@ const char *command_history_next(WINDOW_REC *window, const char *text) } if (*text != '\0' && - (pos == NULL || strcmp(pos->data, text) != 0)) { + (pos == NULL || g_strcmp0(pos->data, text) != 0)) { /* save the old entry to history */ command_history_add(history, text); } diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c index 31d62e10..c607a884 100644 --- a/src/fe-common/core/completion.c +++ b/src/fe-common/core/completion.c @@ -141,7 +141,7 @@ char *word_complete(WINDOW_REC *window, const char *line, int *pos, int erase, i g_return_val_if_fail(pos != NULL, NULL); continue_complete = complist != NULL && *pos == last_line_pos && - strcmp(line, last_line) == 0; + g_strcmp0(line, last_line) == 0; if (erase && !continue_complete) return NULL; @@ -681,7 +681,7 @@ static void sig_complete_set(GList **list, WINDOW_REC *window, g_return_if_fail(line != NULL); if (*line == '\0' || - !strcmp("-clear", line) || !strcmp("-default", line)) + !g_strcmp0("-clear", line) || !g_strcmp0("-default", line)) *list = completion_get_settings(word, -1); else if (*line != '\0' && *word == '\0') { SETTINGS_REC *rec = settings_get_record(line); diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index aefd1034..a171596d 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -287,7 +287,7 @@ static void cmd_channel_add(const char *data) if (g_hash_table_lookup(optlist, "noauto")) rec->autojoin = FALSE; if (botarg != NULL && *botarg != '\0') rec->botmasks = g_strdup(botarg); if (botcmdarg != NULL && *botcmdarg != '\0') rec->autosendcmd = g_strdup(botcmdarg); - if (*password != '\0' && strcmp(password, "-") != 0) rec->password = g_strdup(password); + if (*password != '\0' && g_strcmp0(password, "-") != 0) rec->password = g_strdup(password); signal_emit("channel add fill", 2, rec, optlist); @@ -523,7 +523,7 @@ static void cmd_names(const char *data, SERVER_REC *server, WI_ITEM_REC *item) "names", &optlist, &channel)) return; - if (strcmp(channel, "*") == 0 || *channel == '\0') { + if (g_strcmp0(channel, "*") == 0 || *channel == '\0') { if (!IS_CHANNEL(item)) cmd_param_error(CMDERR_NOT_JOINED); @@ -561,7 +561,7 @@ static void cmd_names(const char *data, SERVER_REC *server, WI_ITEM_REC *item) if (unknowns->len > 1) g_string_truncate(unknowns, unknowns->len-1); - if (unknowns->len > 0 && strcmp(channel, unknowns->str) != 0) + if (unknowns->len > 0 && g_strcmp0(channel, unknowns->str) != 0) signal_emit("command names", 3, unknowns->str, server, item); g_string_free(unknowns, TRUE); diff --git a/src/fe-common/core/fe-exec.c b/src/fe-common/core/fe-exec.c index 9249f432..b5f289ce 100644 --- a/src/fe-common/core/fe-exec.c +++ b/src/fe-common/core/fe-exec.c @@ -161,7 +161,7 @@ static PROCESS_REC *process_find(const char *name, int verbose) for (tmp = processes; tmp != NULL; tmp = tmp->next) { PROCESS_REC *rec = tmp->data; - if (rec->name != NULL && strcmp(rec->name, name) == 0) + if (rec->name != NULL && g_strcmp0(rec->name, name) == 0) return rec; } diff --git a/src/fe-common/core/fe-help.c b/src/fe-common/core/fe-help.c index 4ea7c89f..23a6e701 100644 --- a/src/fe-common/core/fe-help.c +++ b/src/fe-common/core/fe-help.c @@ -37,12 +37,12 @@ static int commands_equal(COMMAND_REC *rec, COMMAND_REC *rec2) if (rec2->category == NULL && rec->category != NULL) return 1; if (rec->category != NULL && rec2->category != NULL) { - i = strcmp(rec->category, rec2->category); + i = g_strcmp0(rec->category, rec2->category); if (i != 0) return i; } - return strcmp(rec->cmd, rec2->cmd); + return g_strcmp0(rec->cmd, rec2->cmd); } static int get_cmd_length(void *data) @@ -176,7 +176,7 @@ static void show_help(const char *data) if (last != NULL && rec->category != NULL && (last->category == NULL || - strcmp(rec->category, last->category) != 0)) { + g_strcmp0(rec->category, last->category) != 0)) { /* category changed */ if (items > 0) { if (!header) { diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index 1a0b8339..533cda31 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -165,7 +165,7 @@ static void cmd_ignore(const char *data) rec = g_new0(IGNORE_REC, 1); rec->mask = mask == NULL || *mask == '\0' || - strcmp(mask, "*") == 0 ? NULL : g_strdup(mask); + g_strcmp0(mask, "*") == 0 ? NULL : g_strdup(mask); rec->channels = channels; } else { g_free_and_null(rec->pattern); diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index 9d68faf9..a39623d2 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -485,7 +485,7 @@ static void autolog_open_check(TEXT_DEST_REC *dest) return; if (target != NULL) - autolog_open(server, server_tag, strcmp(target, "*") ? target : deftarget); + autolog_open(server, server_tag, g_strcmp0(target, "*") ? target : deftarget); } static void log_single_line(WINDOW_REC *window, const char *server_tag, @@ -629,7 +629,7 @@ static void sig_log_create_failed(LOG_REC *log) static void sig_log_new(LOG_REC *log) { if (!settings_get_bool("awaylog_colors") && - strcmp(log->fname, settings_get_str("awaylog_file")) == 0) + g_strcmp0(log->fname, settings_get_str("awaylog_file")) == 0) log->colorizer = log_colorizer_strip; } diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index 1d44bdd9..3bd2b666 100644 --- a/src/fe-common/core/fe-messages.c +++ b/src/fe-common/core/fe-messages.c @@ -249,7 +249,7 @@ static void sig_message_private(SERVER_REC *server, const char *msg, int level = MSGLEVEL_MSGS; /* own message returned by bouncer? */ - int own = (!strcmp(nick, server->nick)); + int own = (!g_strcmp0(nick, server->nick)); query = query_find(server, own ? target : nick); @@ -323,8 +323,8 @@ static void sig_message_own_private(SERVER_REC *server, const char *msg, /* this should only happen if some special target failed and we should display some error message. currently the special targets are only ',' and '.'. */ - g_return_if_fail(strcmp(origtarget, ",") == 0 || - strcmp(origtarget, ".") == 0); + g_return_if_fail(g_strcmp0(origtarget, ",") == 0 || + g_strcmp0(origtarget, ".") == 0); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, *origtarget == ',' ? TXT_NO_MSGS_GOT : @@ -569,7 +569,7 @@ static int printnick_exists(NICK_REC *first, NICK_REC *ignore, while (first != NULL) { if (first != ignore) { printnick = g_hash_table_lookup(printnicks, first); - if (printnick != NULL && strcmp(printnick, nick) == 0) + if (printnick != NULL && g_strcmp0(printnick, nick) == 0) return TRUE; } diff --git a/src/fe-common/core/fe-queries.c b/src/fe-common/core/fe-queries.c index 5cdf87ee..121417e4 100644 --- a/src/fe-common/core/fe-queries.c +++ b/src/fe-common/core/fe-queries.c @@ -331,7 +331,7 @@ static void sig_message_private(SERVER_REC *server, const char *msg, QUERY_REC *query; /* own message returned by bouncer? */ - int own = (!strcmp(nick, server->nick)); + int own = (!g_strcmp0(nick, server->nick)); /* create query window if needed */ query = privmsg_get_query(server, own ? target : nick, FALSE, MSGLEVEL_MSGS); diff --git a/src/fe-common/core/fe-recode.c b/src/fe-common/core/fe-recode.c index dbc43574..829c89e7 100644 --- a/src/fe-common/core/fe-recode.c +++ b/src/fe-common/core/fe-recode.c @@ -45,7 +45,7 @@ static const char *fe_recode_get_target (WI_ITEM_REC *witem) static int fe_recode_compare_func (CONFIG_NODE *node1, CONFIG_NODE *node2) { - return strcmp(node1->key, node2->key); + return g_strcmp0(node1->key, node2->key); } /* SYNTAX: RECODE */ diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index 2dec1d8a..667c68fa 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -185,7 +185,7 @@ static void cmd_server_add(const char *data) if (g_hash_table_lookup(optlist, "proxy")) rec->no_proxy = FALSE; if (g_hash_table_lookup(optlist, "noproxy")) rec->no_proxy = TRUE; - if (*password != '\0' && strcmp(password, "-") != 0) rec->password = g_strdup(password); + if (*password != '\0' && g_strcmp0(password, "-") != 0) rec->password = g_strdup(password); value = g_hash_table_lookup(optlist, "host"); if (value != NULL && *value != '\0') { rec->own_host = g_strdup(value); @@ -264,7 +264,7 @@ static void cmd_server_connect(const char *data) "connect", &optlist, &addr)) return; - if (*addr == '\0' || strcmp(addr, "+") == 0) + if (*addr == '\0' || g_strcmp0(addr, "+") == 0) cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*addr == '+') window_create(NULL, FALSE); diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index 96e03ceb..9c370838 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -53,7 +53,7 @@ static void set_print_pattern(const char *pattern) if (stristr(rec->key, pattern) == NULL) continue; - if (strcmp(last_section, rec->section) != 0) { + if (g_strcmp0(last_section, rec->section) != 0) { /* print section */ printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_SET_TITLE, rec->section); diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index ff3a7085..beb4ed7a 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -168,7 +168,7 @@ static HILIGHT_REC *hilight_find(const char *text, char **channels) if ((channels == NULL && rec->channels == NULL)) return rec; /* no channels - ok */ - if (channels != NULL && strcmp(*channels, "*") == 0) + if (channels != NULL && g_strcmp0(*channels, "*") == 0) return rec; /* ignore channels */ if (channels == NULL || rec->channels == NULL) @@ -306,7 +306,7 @@ void hilight_update_text_dest(TEXT_DEST_REC *dest, HILIGHT_REC *rec) dest->hilight_priority = rec->priority; g_free_and_null(dest->hilight_color); - if (rec->act_color != NULL && strcmp(rec->act_color, "%n") == 0) + if (rec->act_color != NULL && g_strcmp0(rec->act_color, "%n") == 0) dest->level |= MSGLEVEL_NO_ACT; else dest->hilight_color = hilight_get_act_color(rec); diff --git a/src/fe-common/core/keyboard.c b/src/fe-common/core/keyboard.c index bec1502e..eac8525b 100644 --- a/src/fe-common/core/keyboard.c +++ b/src/fe-common/core/keyboard.c @@ -118,7 +118,7 @@ static CONFIG_NODE *key_config_find(const char *key) for (; tmp != NULL; tmp = config_node_next(tmp)) { node = tmp->data; - if (strcmp(config_node_get_str(node, "key", ""), key) == 0) + if (g_strcmp0(config_node_get_str(node, "key", ""), key) == 0) return node; } @@ -211,7 +211,7 @@ static int expand_combo(const char *start, const char *end, GSList **out) for (tmp = info->keys; tmp != NULL; tmp = tmp->next) { KEY_REC *rec = tmp->data; - if (strcmp(rec->data, str) == 0) + if (g_strcmp0(rec->data, str) == 0) list = g_slist_append(list, rec); } @@ -347,7 +347,7 @@ static void key_states_scan_key(const char *key, KEY_REC *rec) { GSList *tmp, *out; - if (strcmp(rec->info->id, "key") == 0) + if (g_strcmp0(rec->info->id, "key") == 0) return; out = g_slist_append(NULL, g_string_new(NULL)); @@ -383,7 +383,7 @@ static void key_states_rescan(void) g_tree_foreach(key_states, (GTraverseFunc) key_state_destroy, NULL); g_tree_destroy(key_states); - key_states = g_tree_new((GCompareFunc) strcmp); + key_states = g_tree_new((GCompareFunc) g_strcmp0); temp = g_string_new(NULL); g_hash_table_foreach(keys, (GHFunc) key_states_scan_key, temp); @@ -860,7 +860,7 @@ void keyboard_init(void) default_keys = g_hash_table_new((GHashFunc) g_str_hash, (GCompareFunc) g_str_equal); keyinfos = NULL; - key_states = g_tree_new((GCompareFunc) strcmp); + key_states = g_tree_new((GCompareFunc) g_strcmp0); key_config_frozen = 0; memset(used_keys, 0, sizeof(used_keys)); diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c index c0741cef..0ef98fee 100644 --- a/src/fe-common/core/themes.c +++ b/src/fe-common/core/themes.c @@ -895,7 +895,7 @@ THEME_REC *theme_load(const char *setname) name = g_strdup(setname); p = strrchr(name, '.'); - if (p != NULL && strcmp(p, ".theme") == 0) { + if (p != NULL && g_strcmp0(p, ".theme") == 0) { /* remove the trailing .theme */ *p = '\0'; } @@ -1358,9 +1358,9 @@ static void read_settings(void) theme = settings_get_str("theme"); len = strlen(current_theme->name); - if (strcmp(current_theme->name, theme) != 0 && + if (g_strcmp0(current_theme->name, theme) != 0 && (strncmp(current_theme->name, theme, len) != 0 || - strcmp(theme+len, ".theme") != 0)) + g_strcmp0(theme+len, ".theme") != 0)) change_theme(theme, TRUE); } diff --git a/src/fe-common/core/window-commands.c b/src/fe-common/core/window-commands.c index 61357324..c6ab68c0 100644 --- a/src/fe-common/core/window-commands.c +++ b/src/fe-common/core/window-commands.c @@ -127,7 +127,7 @@ static void cmd_window_info(WINDOW_REC *win) win->active_server->tag : "NONE"); } else { if (win->active_server != NULL && - strcmp(win->active_server->tag, win->servertag) != 0) + g_strcmp0(win->active_server->tag, win->servertag) != 0) g_warning("Active server isn't the sticky server!"); printformat_window(win, MSGLEVEL_CLIENTCRAP, @@ -609,7 +609,7 @@ static void cmd_window_name(const char *data) if (win == NULL || win == active_win) window_set_name(active_win, data); else if (active_win->name == NULL || - strcmp(active_win->name, data) != 0) { + g_strcmp0(active_win->name, data) != 0) { printformat_window(active_win, MSGLEVEL_CLIENTERROR, TXT_WINDOW_NAME_NOT_UNIQUE, data); } diff --git a/src/fe-common/irc/dcc/fe-dcc-chat.c b/src/fe-common/irc/dcc/fe-dcc-chat.c index 101aeb31..e2706ba3 100644 --- a/src/fe-common/irc/dcc/fe-dcc-chat.c +++ b/src/fe-common/irc/dcc/fe-dcc-chat.c @@ -243,7 +243,7 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) return; /* handle only DCC messages */ - if (strcmp(target, "*") == 0) + if (g_strcmp0(target, "*") == 0) dcc = item_get_dcc(item); else if (*target == '=') dcc = dcc_chat_find_id(target+1); diff --git a/src/fe-common/irc/fe-events-numeric.c b/src/fe-common/irc/fe-events-numeric.c index d6c02d9f..ec7669ab 100644 --- a/src/fe-common/irc/fe-events-numeric.c +++ b/src/fe-common/irc/fe-events-numeric.c @@ -427,7 +427,7 @@ static void event_no_such_nick(IRC_SERVER_REC *server, const char *data, g_return_if_fail(data != NULL); params = event_get_params(data, 2, NULL, &unick); - if (!strcmp(unick, "*")) + if (!g_strcmp0(unick, "*")) /* more information will be in the description, * e.g. * :Target left IRC. Failed to deliver: [hi] */ print_event_received(server, data, nick, FALSE); @@ -605,7 +605,7 @@ static void print_event_received(IRC_SERVER_REC *server, const char *data, recoded = recode_in(SERVER(server), args, NULL); format = nick == NULL || server->real_address == NULL || - strcmp(nick, server->real_address) == 0 ? + g_strcmp0(nick, server->real_address) == 0 ? IRCTXT_DEFAULT_EVENT : IRCTXT_DEFAULT_EVENT_SERVER; printformat(server, target, MSGLEVEL_CRAP, format, nick, recoded, current_server_event); diff --git a/src/fe-common/irc/fe-irc-commands.c b/src/fe-common/irc/fe-irc-commands.c index b380c214..a23facbd 100644 --- a/src/fe-common/irc/fe-irc-commands.c +++ b/src/fe-common/irc/fe-irc-commands.c @@ -110,7 +110,7 @@ static void cmd_notice(const char *data, IRC_SERVER_REC *server, if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) return; - if (strcmp(target, "*") == 0) + if (g_strcmp0(target, "*") == 0) target = item == NULL ? "" : window_item_get_target(item); if (*target == '\0' || *msg == '\0') @@ -133,7 +133,7 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server, if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) return; - if (strcmp(target, "*") == 0) + if (g_strcmp0(target, "*") == 0) target = item == NULL ? "" : window_item_get_target(item); if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -162,7 +162,7 @@ static void cmd_nctcp(const char *data, IRC_SERVER_REC *server, if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &text)) return; - if (strcmp(target, "*") == 0) + if (g_strcmp0(target, "*") == 0) target = item == NULL ? "" : window_item_get_target(item); if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -262,7 +262,7 @@ static void cmd_ban(const char *data, IRC_SERVER_REC *server, if (chanrec == NULL && *channel == '\0') cmd_param_error(CMDERR_NOT_JOINED); - if (*channel != '\0' && strcmp(channel, "*") != 0) + if (*channel != '\0' && g_strcmp0(channel, "*") != 0) chanrec = irc_channel_find(server, channel); if (chanrec == NULL || !chanrec->synced) { diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index 314f4f53..94d1ad4a 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -178,7 +178,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, if (ischannel(*target)) { item = irc_channel_find(server, target); } else { - own = (!strcmp(nick, server->nick)); + own = (!g_strcmp0(nick, server->nick)); item = privmsg_get_query(SERVER(server), own ? target : nick, FALSE, level); } diff --git a/src/fe-common/irc/fe-modes.c b/src/fe-common/irc/fe-modes.c index 027d7a76..e5317c0f 100644 --- a/src/fe-common/irc/fe-modes.c +++ b/src/fe-common/irc/fe-modes.c @@ -135,7 +135,7 @@ static void msg_multi_mode(IRC_CHANNEL_REC *channel, const char *sender, signal_add("print starting", (SIGNAL_FUNC) sig_print_starting); rec = mode_find_channel(channel); - if (rec != NULL && strcmp(rec->mode, mode) != 0) { + if (rec != NULL && g_strcmp0(rec->mode, mode) != 0) { /* different mode than last time, show and remove the old */ print_mode(rec); mode_destroy(rec); diff --git a/src/fe-common/irc/fe-whois.c b/src/fe-common/irc/fe-whois.c index a9c3775e..117df120 100644 --- a/src/fe-common/irc/fe-whois.c +++ b/src/fe-common/irc/fe-whois.c @@ -134,8 +134,8 @@ static void event_whois_realhost(IRC_SERVER_REC *server, const char *data) /* real hostname */ params = event_get_params(data, 5, NULL, &nick, &txt_real, &txt_hostname, &hostname); - if (strcmp(txt_real, "real") != 0 || - strcmp(txt_hostname, "hostname") != 0) { + if (g_strcmp0(txt_real, "real") != 0 || + g_strcmp0(txt_hostname, "hostname") != 0) { /* :... from */ g_free(params); params = event_get_params(data, 3, NULL, &nick, &hostname); @@ -219,7 +219,7 @@ static void event_whois_usermode(IRC_SERVER_REC *server, const char *data) params = event_get_params(data, 4, NULL, &txt_usermodes, &nick, &usermode); - if (strcmp(txt_usermodes, "usermodes") == 0) { + if (g_strcmp0(txt_usermodes, "usermodes") == 0) { /* usermodes usermode */ printformat(server, nick, MSGLEVEL_CRAP, IRCTXT_WHOIS_USERMODE, nick, usermode); diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index e93f2293..edc4c55d 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -392,7 +392,7 @@ static void sig_gui_key_pressed(gpointer keyp) str[g_unichar_to_utf8(key, str)] = '\0'; } - if (strcmp(str, "^") == 0) { + if (g_strcmp0(str, "^") == 0) { /* change it as ^-, that is an invalid control char */ str[1] = '-'; str[2] = '\0'; diff --git a/src/fe-text/statusbar-config.c b/src/fe-text/statusbar-config.c index deaa1b5d..7b3fe252 100644 --- a/src/fe-text/statusbar-config.c +++ b/src/fe-text/statusbar-config.c @@ -95,7 +95,7 @@ statusbar_config_find(STATUSBAR_GROUP_REC *group, const char *name) for (tmp = group->config_bars; tmp != NULL; tmp = tmp->next) { STATUSBAR_CONFIG_REC *config = tmp->data; - if (strcmp(config->name, name) == 0) + if (g_strcmp0(config->name, name) == 0) return config; } @@ -137,7 +137,7 @@ static void statusbar_read_item(STATUSBAR_CONFIG_REC *bar, CONFIG_NODE *node) int priority, right_alignment; priority = config_node_get_int(node, "priority", 0); - right_alignment = strcmp(config_node_get_str(node, "alignment", ""), "right") == 0; + right_alignment = g_strcmp0(config_node_get_str(node, "alignment", ""), "right") == 0; statusbar_item_config_create(bar, node->key, priority, right_alignment); } diff --git a/src/fe-text/statusbar.c b/src/fe-text/statusbar.c index b340553f..5448243a 100644 --- a/src/fe-text/statusbar.c +++ b/src/fe-text/statusbar.c @@ -129,7 +129,7 @@ STATUSBAR_GROUP_REC *statusbar_group_find(const char *name) for (tmp = statusbar_groups; tmp != NULL; tmp = tmp->next) { STATUSBAR_GROUP_REC *rec = tmp->data; - if (strcmp(rec->name, name) == 0) + if (g_strcmp0(rec->name, name) == 0) return rec; } @@ -617,7 +617,7 @@ STATUSBAR_REC *statusbar_find(STATUSBAR_GROUP_REC *group, const char *name, STATUSBAR_REC *rec = tmp->data; if (rec->parent_window == window && - strcmp(rec->config->name, name) == 0) + g_strcmp0(rec->config->name, name) == 0) return rec; } diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c index d16987fe..0516cc5f 100644 --- a/src/fe-text/terminfo-core.c +++ b/src/fe-text/terminfo-core.c @@ -646,11 +646,11 @@ static int term_setup(TERM_REC *term) str = g_string_new(NULL); if (term->TI_sgr0) g_string_append(str, term->TI_sgr0); - if (term->TI_rmul && (term->TI_sgr0 == NULL || strcmp(term->TI_rmul, term->TI_sgr0) != 0)) + if (term->TI_rmul && (term->TI_sgr0 == NULL || g_strcmp0(term->TI_rmul, term->TI_sgr0) != 0)) g_string_append(str, term->TI_rmul); - if (term->TI_rmso && (term->TI_sgr0 == NULL || strcmp(term->TI_rmso, term->TI_sgr0) != 0)) + if (term->TI_rmso && (term->TI_sgr0 == NULL || g_strcmp0(term->TI_rmso, term->TI_sgr0) != 0)) g_string_append(str, term->TI_rmso); - if (term->TI_ritm && (term->TI_sgr0 == NULL || strcmp(term->TI_ritm, term->TI_sgr0) != 0)) + if (term->TI_ritm && (term->TI_sgr0 == NULL || g_strcmp0(term->TI_ritm, term->TI_sgr0) != 0)) g_string_append(str, term->TI_ritm); term->TI_normal = str->str; g_string_free(str, FALSE); diff --git a/src/irc/core/bans.c b/src/irc/core/bans.c index 38c81aab..b60e681b 100644 --- a/src/irc/core/bans.c +++ b/src/irc/core/bans.c @@ -188,7 +188,7 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server, item, &channel, &nicks)) return; if (!ischannel(*channel)) cmd_param_error(CMDERR_NOT_JOINED); if (*nicks == '\0') { - if (strcmp(data, "*") != 0) + if (g_strcmp0(data, "*") != 0) cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); /* /BAN * or /UNBAN * - ban/unban everyone */ nicks = (char *) data; @@ -318,7 +318,7 @@ static void cmd_unban(const char *data, IRC_SERVER_REC *server, void *item) static void read_settings(void) { if (default_ban_type_str != NULL && - strcmp(default_ban_type_str, settings_get_str("ban_type")) == 0) + g_strcmp0(default_ban_type_str, settings_get_str("ban_type")) == 0) return; g_free_not_null(default_ban_type_str); diff --git a/src/irc/core/channel-events.c b/src/irc/core/channel-events.c index 6fdfeef3..6cb9b088 100644 --- a/src/irc/core/channel-events.c +++ b/src/irc/core/channel-events.c @@ -270,7 +270,7 @@ static void event_join(IRC_SERVER_REC *server, const char *data, const char *nic } chanrec->joined = TRUE; - if (strcmp(chanrec->name, channel) != 0) { + if (g_strcmp0(chanrec->name, channel) != 0) { g_free(chanrec->name); chanrec->name = g_strdup(channel); } diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index 7c3d3f5f..e7fb5067 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -72,7 +72,7 @@ static void cmd_notice(const char *data, IRC_SERVER_REC *server, if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) return; - if (strcmp(target, "*") == 0) + if (g_strcmp0(target, "*") == 0) target = item == NULL ? NULL : window_item_get_target(item); if (target == NULL || *target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -99,7 +99,7 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server, if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) return; - if (strcmp(target, "*") == 0) + if (g_strcmp0(target, "*") == 0) target = item == NULL ? NULL : window_item_get_target(item); if (target == NULL || *target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -133,7 +133,7 @@ static void cmd_nctcp(const char *data, IRC_SERVER_REC *server, if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) return; - if (strcmp(target, "*") == 0) + if (g_strcmp0(target, "*") == 0) target = item == NULL ? NULL : window_item_get_target(item); if (target == NULL || *target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -238,7 +238,7 @@ static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *it return; if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - if (*channame == '\0' || strcmp(channame, "*") == 0) { + if (*channame == '\0' || g_strcmp0(channame, "*") == 0) { if (!IS_IRC_CHANNEL(item)) cmd_param_error(CMDERR_NOT_JOINED); @@ -284,13 +284,13 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server, if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channel, &rest)) return; - if (strcmp(channel, "*") == 0 || *channel == '\0') { + if (g_strcmp0(channel, "*") == 0 || *channel == '\0') { if (!IS_IRC_CHANNEL(item)) cmd_param_error(CMDERR_NOT_JOINED); channel = IRC_CHANNEL(item)->name; } - if (strcmp(channel, "**") == 0) { + if (g_strcmp0(channel, "**") == 0) { /* ** displays all nicks.. */ *channel = '\0'; } @@ -313,14 +313,14 @@ static void cmd_names(const char *data, IRC_SERVER_REC *server, PARAM_FLAG_GETREST, "names", &optlist, &channel)) return; - if (strcmp(channel, "*") == 0 || *channel == '\0') { + if (g_strcmp0(channel, "*") == 0 || *channel == '\0') { if (!IS_IRC_CHANNEL(item)) cmd_param_error(CMDERR_NOT_JOINED); channel = IRC_CHANNEL(item)->name; } - if (strcmp(channel, "**") == 0) { + if (g_strcmp0(channel, "**") == 0) { /* ** displays all nicks.. */ irc_send_cmd(server, "NAMES"); } else { @@ -409,7 +409,7 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server, query = qserver = queryitem->name; } - if (strcmp(query, "*") == 0 && + if (g_strcmp0(query, "*") == 0 && g_hash_table_lookup(optlist, "yes") == NULL) cmd_param_error(CMDERR_NOT_GOOD_IDEA); @@ -810,7 +810,7 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, for (ptr = server->knockoutlist; ptr != NULL; ptr = ptr->next) { rec = ptr->data; if (channel == rec->channel && - !strcmp(rec->ban, banmasks)) + !g_strcmp0(rec->ban, banmasks)) break; } if (ptr == NULL) { diff --git a/src/irc/core/irc-queries.c b/src/irc/core/irc-queries.c index ac1a72a1..72c17df1 100644 --- a/src/irc/core/irc-queries.c +++ b/src/irc/core/irc-queries.c @@ -67,13 +67,13 @@ static void check_query_changes(IRC_SERVER_REC *server, const char *nick, if (query == NULL) return; - if (strcmp(query->name, nick) != 0) { + if (g_strcmp0(query->name, nick) != 0) { /* upper/lowercase chars in nick changed */ query_change_nick(query, nick); } if (address != NULL && (query->address == NULL || - strcmp(query->address, address) != 0)) { + g_strcmp0(query->address, address) != 0)) { /* host changed */ query_change_address(query, address); } @@ -109,7 +109,7 @@ static void event_nick(SERVER_REC *server, const char *data, query = query_find(server, orignick); if (query != NULL) { params = event_get_params(data, 1, &nick); - if (strcmp(query->name, nick) != 0) + if (g_strcmp0(query->name, nick) != 0) query_change_nick(query, nick); g_free(params); } diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index baf8a0d2..d7122eae 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -638,7 +638,7 @@ static void event_connected(IRC_SERVER_REC *server, const char *data, const char params = event_get_params(data, 1, &nick); - if (strcmp(server->nick, nick) != 0) { + if (g_strcmp0(server->nick, nick) != 0) { /* nick changed unexpectedly .. connected via proxy, etc. */ g_free(server->nick); server->nick = g_strdup(nick); diff --git a/src/irc/core/modes.c b/src/irc/core/modes.c index ebaf4b8f..a812691c 100644 --- a/src/irc/core/modes.c +++ b/src/irc/core/modes.c @@ -398,7 +398,7 @@ void parse_channel_modes(IRC_CHANNEL_REC *channel, const char *setby, old_key = NULL; } - if (strcmp(newmode->str, channel->mode) != 0) { + if (g_strcmp0(newmode->str, channel->mode) != 0) { g_free(channel->mode); channel->mode = g_strdup(newmode->str); @@ -842,7 +842,7 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server, return; } - if (strcmp(target, "*") == 0) { + if (g_strcmp0(target, "*") == 0) { if (!IS_IRC_CHANNEL(channel)) cmd_param_error(CMDERR_NOT_JOINED); diff --git a/src/irc/core/servers-redirect.c b/src/irc/core/servers-redirect.c index 518248cb..f0a285df 100644 --- a/src/irc/core/servers-redirect.c +++ b/src/irc/core/servers-redirect.c @@ -339,7 +339,7 @@ static GSList *redirect_cmd_list_find(GSList *list, const char *event) while (list != NULL) { const char *str = list->data; - if (strcmp(str, event) == 0) + if (g_strcmp0(str, event) == 0) break; list = list->next->next; } @@ -365,7 +365,7 @@ static const char *redirect_match(REDIRECT_REC *redirect, const char *event, use the default signal */ signal = NULL; for (tmp = redirect->signals; tmp != NULL; tmp = tmp->next->next) { - if (strcmp(tmp->data, event) == 0) { + if (g_strcmp0(tmp->data, event) == 0) { signal = tmp->next->data; break; } @@ -527,7 +527,7 @@ server_redirect_get(IRC_SERVER_REC *server, const char *prefix, next = ptr->next; r = ptr->data; if (prefix != NULL && r->prefix != NULL && - strcmp(prefix, r->prefix)) { + g_strcmp0(prefix, r->prefix)) { /* not from this server */ continue; } diff --git a/src/irc/dcc/dcc-autoget.c b/src/irc/dcc/dcc-autoget.c index 4768641b..38170c56 100644 --- a/src/irc/dcc/dcc-autoget.c +++ b/src/irc/dcc/dcc-autoget.c @@ -57,7 +57,7 @@ static void sig_dcc_request(GET_DCC_REC *dcc, const char *nickaddr) /* don't autoget files beginning with a dot, if download dir is our home dir (stupid kludge for stupid people) */ if (*dcc->arg == '.' && - strcmp(settings_get_str("dcc_download_path"), "~") == 0) + g_strcmp0(settings_get_str("dcc_download_path"), "~") == 0) return; /* check file size limit, NOTE: it's still possible to send a diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c index 8ee4decd..e3dbe72d 100644 --- a/src/irc/dcc/dcc-chat.c +++ b/src/irc/dcc/dcc-chat.c @@ -191,7 +191,7 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) return; /* handle only DCC messages */ - if (strcmp(target, "*") == 0) + if (g_strcmp0(target, "*") == 0) dcc = item_get_dcc(item); else if (*target == '=') dcc = dcc_chat_find_id(target+1); @@ -625,7 +625,7 @@ static void ctcp_msg_dcc_chat(IRC_SERVER_REC *server, const char *data, g_strfreev(params); return; } - passive = paramcount == 4 && strcmp(params[2], "0") == 0; + passive = paramcount == 4 && g_strcmp0(params[2], "0") == 0; dcc = DCC_CHAT(dcc_find_request(DCC_CHAT_TYPE, nick, NULL)); if (dcc != NULL) { diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c index 69fdc746..1208b5c5 100644 --- a/src/irc/dcc/dcc-get.c +++ b/src/irc/dcc/dcc-get.c @@ -554,7 +554,7 @@ void cmd_dcc_receive(const char *data, DCC_GET_FUNC accept_func, next = tmp->next; if (IS_DCC_GET(dcc) && g_ascii_strcasecmp(dcc->nick, nick) == 0 && (dcc_is_waiting_user(dcc) || dcc->from_dccserver) && - (*fname == '\0' || strcmp(dcc->arg, fname) == 0)) { + (*fname == '\0' || g_strcmp0(dcc->arg, fname) == 0)) { found = TRUE; if (!dcc_is_passive(dcc)) accept_func(dcc); diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index 6f0d5c81..17f6c477 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -149,7 +149,7 @@ DCC_REC *dcc_find_request(int type, const char *nick, const char *arg) if (dcc->type == type && !dcc_is_connected(dcc) && g_ascii_strcasecmp(dcc->nick, nick) == 0 && - (arg == NULL || strcmp(dcc->arg, arg) == 0)) + (arg == NULL || g_strcmp0(dcc->arg, arg) == 0)) return dcc; } @@ -516,7 +516,7 @@ static void cmd_dcc_close(char *data, IRC_SERVER_REC *server) next = tmp->next; if (dcc->type == type && g_ascii_strcasecmp(dcc->nick, nick) == 0 && - (*arg == '\0' || strcmp(dcc->arg, arg) == 0)) { + (*arg == '\0' || g_strcmp0(dcc->arg, arg) == 0)) { dcc_reject(dcc, server); found = TRUE; } diff --git a/src/irc/notifylist/notifylist.c b/src/irc/notifylist/notifylist.c index b0b7ee1c..573f7a7f 100644 --- a/src/irc/notifylist/notifylist.c +++ b/src/irc/notifylist/notifylist.c @@ -91,7 +91,7 @@ int notifylist_ircnets_match(NOTIFYLIST_REC *rec, const char *ircnet) if (rec->ircnets == NULL) return TRUE; if (ircnet == NULL) return FALSE; - if (strcmp(ircnet, "*") == 0) return TRUE; + if (g_strcmp0(ircnet, "*") == 0) return TRUE; for (tmp = rec->ircnets; *tmp != NULL; tmp++) { if (g_ascii_strcasecmp(*tmp, ircnet) == 0) diff --git a/src/irc/proxy/dump.c b/src/irc/proxy/dump.c index 80fd7c2e..3d7bf546 100644 --- a/src/irc/proxy/dump.c +++ b/src/irc/proxy/dump.c @@ -209,7 +209,7 @@ static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client) void proxy_client_reset_nick(CLIENT_REC *client) { if (client->server == NULL || - strcmp(client->nick, client->server->nick) == 0) + g_strcmp0(client->nick, client->server->nick) == 0) return; proxy_outdata(client, ":%s!proxy NICK :%s\n", diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 33392285..4c3bcf68 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -82,7 +82,7 @@ static void grab_who(CLIENT_REC *client, const char *channel) arg = g_string_new(channel); for (tmp = list, count = 0; *tmp != NULL; tmp++, count++) { - if (strcmp(*tmp, "0") == 0) { + if (g_strcmp0(*tmp, "0") == 0) { /* /who 0 displays everyone */ **tmp = '*'; } @@ -106,18 +106,18 @@ static void handle_client_connect_cmd(CLIENT_REC *client, password = settings_get_str("irssiproxy_password"); - if (password != NULL && strcmp(cmd, "PASS") == 0) { - if (strcmp(password, args) == 0) + if (password != NULL && g_strcmp0(cmd, "PASS") == 0) { + if (g_strcmp0(password, args) == 0) client->pass_sent = TRUE; else { /* wrong password! */ remove_client(client); return; } - } else if (strcmp(cmd, "NICK") == 0) { + } else if (g_strcmp0(cmd, "NICK") == 0) { g_free_not_null(client->nick); client->nick = g_strdup(args); - } else if (strcmp(cmd, "USER") == 0) { + } else if (g_strcmp0(cmd, "USER") == 0) { client->user_sent = TRUE; } @@ -141,12 +141,12 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, return; } - if (strcmp(cmd, "QUIT") == 0) { + if (g_strcmp0(cmd, "QUIT") == 0) { remove_client(client); return; } - if (strcmp(cmd, "PING") == 0) { + if (g_strcmp0(cmd, "PING") == 0) { /* Reply to PING, if the target parameter is either proxy_adress, our own nick or empty. */ char *params, *origin, *target; @@ -164,7 +164,7 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, g_free(params); } - if (strcmp(cmd, "PROXY") == 0) { + if (g_strcmp0(cmd, "PROXY") == 0) { if (g_ascii_strcasecmp(args, "CTCP ON") == 0) { /* client wants all ctcps */ client->want_ctcp = 1; @@ -200,11 +200,11 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, } /* check if the command could be redirected */ - if (strcmp(cmd, "WHO") == 0) + if (g_strcmp0(cmd, "WHO") == 0) grab_who(client, args); - else if (strcmp(cmd, "WHOWAS") == 0) + else if (g_strcmp0(cmd, "WHOWAS") == 0) proxy_redirect_event(client, "whowas", 1, args, -1); - else if (strcmp(cmd, "WHOIS") == 0) { + else if (g_strcmp0(cmd, "WHOIS") == 0) { char *p; /* convert dots to spaces */ @@ -212,11 +212,11 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, if (*p == ',') *p = ' '; proxy_redirect_event(client, "whois", 1, args, TRUE); - } else if (strcmp(cmd, "ISON") == 0) + } else if (g_strcmp0(cmd, "ISON") == 0) proxy_redirect_event(client, "ison", 1, args, -1); - else if (strcmp(cmd, "USERHOST") == 0) + else if (g_strcmp0(cmd, "USERHOST") == 0) proxy_redirect_event(client, "userhost", 1, args, -1); - else if (strcmp(cmd, "MODE") == 0) { + else if (g_strcmp0(cmd, "MODE") == 0) { /* convert dots to spaces */ char *slist, *str, mode, *p; int argc; @@ -252,7 +252,7 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, } g_free(str); g_free(slist); - } else if (strcmp(cmd, "PRIVMSG") == 0) { + } else if (g_strcmp0(cmd, "PRIVMSG") == 0) { /* send the message to other clients as well */ char *params, *target, *msg; @@ -283,9 +283,9 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, } ignore_next = FALSE; g_free(params); - } else if (strcmp(cmd, "PING") == 0) { + } else if (g_strcmp0(cmd, "PING") == 0) { proxy_redirect_event(client, "ping", 1, NULL, TRUE); - } else if (strcmp(cmd, "AWAY") == 0) { + } else if (g_strcmp0(cmd, "AWAY") == 0) { /* set the away reason */ if (args != NULL) { g_free(client->server->away_reason); @@ -347,7 +347,7 @@ static void sig_listen(LISTEN_REC *listen) rec->listen = listen; rec->handle = sendbuf; rec->host = g_strdup(host); - if (strcmp(listen->ircnet, "*") == 0) { + if (g_strcmp0(listen->ircnet, "*") == 0) { rec->proxy_address = g_strdup("irc.proxy"); rec->server = servers == NULL ? NULL : IRC_SERVER(servers->data); } else { @@ -415,7 +415,7 @@ static void sig_server_event(IRC_SERVER_REC *server, const char *line, } } - if (strcmp(event, "event privmsg") == 0 && + if (g_strcmp0(event, "event privmsg") == 0 && strstr(args, " :\001") != NULL && strstr(args, " :\001ACTION") == NULL) { /* CTCP - either answer ourself or forward it to one client */ @@ -435,8 +435,8 @@ static void sig_server_event(IRC_SERVER_REC *server, const char *line, return; } - if (strcmp(event, "event ping") == 0 || - strcmp(event, "event pong") == 0) { + if (g_strcmp0(event, "event ping") == 0 || + g_strcmp0(event, "event pong") == 0) { /* We want to answer ourself to PINGs and CTCPs. Also hide PONGs from clients. */ g_free(event); @@ -462,7 +462,7 @@ static void event_connected(IRC_SERVER_REC *server) CLIENT_REC *rec = tmp->data; if (rec->connected && rec->server == NULL && - (strcmp(rec->listen->ircnet, "*") == 0 || + (g_strcmp0(rec->listen->ircnet, "*") == 0 || (chatnet != NULL && g_ascii_strcasecmp(chatnet, rec->listen->ircnet) == 0))) { proxy_outdata(rec, ":%s NOTICE %s :Connected to server\n", diff --git a/src/lib-config/set.c b/src/lib-config/set.c index 61a101fb..3d6001e1 100644 --- a/src/lib-config/set.c +++ b/src/lib-config/set.c @@ -105,7 +105,7 @@ void config_node_set_str(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, } if (node != NULL) { - if (strcmp(node->value, value) == 0) + if (g_strcmp0(node->value, value) == 0) return; g_free(node->value); } else { diff --git a/src/perl/perl-core.c b/src/perl/perl-core.c index eb1bddee..793f9375 100644 --- a/src/perl/perl-core.c +++ b/src/perl/perl-core.c @@ -44,7 +44,7 @@ static int print_script_errors; static char *perl_args[] = {"", "-e", "0"}; #define IS_PERL_SCRIPT(file) \ - (strlen(file) > 3 && strcmp(file+strlen(file)-3, ".pl") == 0) + (strlen(file) > 3 && g_strcmp0(file+strlen(file)-3, ".pl") == 0) static void perl_script_destroy_package(PERL_SCRIPT_REC *script) { @@ -314,7 +314,7 @@ PERL_SCRIPT_REC *perl_script_find(const char *name) for (tmp = perl_scripts; tmp != NULL; tmp = tmp->next) { PERL_SCRIPT_REC *rec = tmp->data; - if (strcmp(rec->name, name) == 0) + if (g_strcmp0(rec->name, name) == 0) return rec; } @@ -331,7 +331,7 @@ PERL_SCRIPT_REC *perl_script_find_package(const char *package) for (tmp = perl_scripts; tmp != NULL; tmp = tmp->next) { PERL_SCRIPT_REC *rec = tmp->data; - if (strcmp(rec->package, package) == 0) + if (g_strcmp0(rec->package, package) == 0) return rec; } diff --git a/src/perl/perl-fe.c b/src/perl/perl-fe.c index 8e8469e9..2abc75c0 100644 --- a/src/perl/perl-fe.c +++ b/src/perl/perl-fe.c @@ -170,7 +170,7 @@ static void cmd_load(const char *data, SERVER_REC *server, void *item) return; len = strlen(rootmodule); - if (len > 3 && strcmp(rootmodule + len - 3, ".pl") == 0) { + if (len > 3 && g_strcmp0(rootmodule + len - 3, ".pl") == 0) { /* make /LOAD script.pl work as expected */ signal_stop(); cmd_script_load(data); diff --git a/src/perl/perl-signals.c b/src/perl/perl-signals.c index 1f602c66..007f7ad5 100644 --- a/src/perl/perl-signals.c +++ b/src/perl/perl-signals.c @@ -99,14 +99,14 @@ void perl_signal_args_to_c( if (!SvOK(arg)) { c_arg = NULL; - } else if (strcmp(rec->args[n], "string") == 0) { + } else if (g_strcmp0(rec->args[n], "string") == 0) { c_arg = SvPV_nolen(arg); - } else if (strcmp(rec->args[n], "int") == 0) { + } else if (g_strcmp0(rec->args[n], "int") == 0) { c_arg = (void *)SvIV(arg); - } else if (strcmp(rec->args[n], "ulongptr") == 0) { + } else if (g_strcmp0(rec->args[n], "ulongptr") == 0) { saved_args[n].v_ulong = SvUV(arg); c_arg = &saved_args[n].v_ulong; - } else if (strcmp(rec->args[n], "intptr") == 0) { + } else if (g_strcmp0(rec->args[n], "intptr") == 0) { saved_args[n].v_int = SvIV(SvRV(arg)); c_arg = &saved_args[n].v_int; } else if (strncmp(rec->args[n], "glistptr_", 9) == 0) { @@ -122,7 +122,7 @@ void perl_signal_args_to_c( } av = (AV *)t; - is_str = strcmp(rec->args[n]+9, "char*") == 0; + is_str = g_strcmp0(rec->args[n]+9, "char*") == 0; gl = NULL; count = av_len(av) + 1; @@ -181,7 +181,7 @@ void perl_signal_args_to_c( continue; } - if (strcmp(rec->args[n], "intptr") == 0) { + if (g_strcmp0(rec->args[n], "intptr") == 0) { SV *t = SvRV(arg); SvIOK_only(t); SvIV_set(t, saved_args[n].v_int); @@ -192,8 +192,8 @@ void perl_signal_args_to_c( AV *av; GList *gl, *tmp; - is_iobject = strcmp(rec->args[n]+9, "iobject") == 0; - is_str = strcmp(rec->args[n]+9, "char*") == 0; + is_iobject = g_strcmp0(rec->args[n]+9, "iobject") == 0; + is_str = g_strcmp0(rec->args[n]+9, "char*") == 0; av = (AV *)SvRV(arg); av_clear(av); @@ -245,8 +245,8 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func, GList *tmp, **ptr; int is_iobject, is_str; - is_iobject = strcmp(rec->args[n]+9, "iobject") == 0; - is_str = strcmp(rec->args[n]+9, "char*") == 0; + is_iobject = g_strcmp0(rec->args[n]+9, "iobject") == 0; + is_str = g_strcmp0(rec->args[n]+9, "char*") == 0; av = newAV(); ptr = arg; @@ -258,22 +258,22 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func, } saved_args[n] = perlarg = newRV_noinc((SV *) av); - } else if (strcmp(rec->args[n], "int") == 0) + } else if (g_strcmp0(rec->args[n], "int") == 0) perlarg = newSViv((IV)arg); else if (arg == NULL) perlarg = &PL_sv_undef; - else if (strcmp(rec->args[n], "string") == 0) + else if (g_strcmp0(rec->args[n], "string") == 0) perlarg = new_pv(arg); - else if (strcmp(rec->args[n], "ulongptr") == 0) + else if (g_strcmp0(rec->args[n], "ulongptr") == 0) perlarg = newSViv(*(unsigned long *) arg); - else if (strcmp(rec->args[n], "intptr") == 0) + else if (g_strcmp0(rec->args[n], "intptr") == 0) saved_args[n] = perlarg = newRV_noinc(newSViv(*(int *) arg)); else if (strncmp(rec->args[n], "gslist_", 7) == 0) { /* linked list - push as AV */ GSList *tmp; int is_iobject; - is_iobject = strcmp(rec->args[n]+7, "iobject") == 0; + is_iobject = g_strcmp0(rec->args[n]+7, "iobject") == 0; av = newAV(); for (tmp = arg; tmp != NULL; tmp = tmp->next) { sv = is_iobject ? iobject_bless((SERVER_REC *) tmp->data) : @@ -282,12 +282,12 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func, } perlarg = newRV_noinc((SV *) av); - } else if (strcmp(rec->args[n], "iobject") == 0) { + } else if (g_strcmp0(rec->args[n], "iobject") == 0) { /* "irssi object" - any struct that has "int type; int chat_type" as it's first variables (server, channel, ..) */ perlarg = iobject_bless((SERVER_REC *) arg); - } else if (strcmp(rec->args[n], "siobject") == 0) { + } else if (g_strcmp0(rec->args[n], "siobject") == 0) { /* "simple irssi object" - any struct that has int type; as it's first variable (dcc) */ perlarg = simple_iobject_bless((SERVER_REC *) arg); @@ -317,7 +317,7 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func, if (saved_args[n] == NULL) continue; - if (strcmp(rec->args[n], "intptr") == 0) { + if (g_strcmp0(rec->args[n], "intptr") == 0) { int *val = arg; *val = SvIV(SvRV(saved_args[n])); } else if (strncmp(rec->args[n], "glistptr_", 9) == 0) { @@ -338,7 +338,7 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func, out = g_list_append(out, val); } - if (strcmp(rec->args[n]+9, "char*") == 0) + if (g_strcmp0(rec->args[n]+9, "char*") == 0) g_list_foreach(*ret, (GFunc) g_free, NULL); g_list_free(*ret); *ret = out; @@ -434,7 +434,7 @@ 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) && \ - strcmp(SvPV_nolen(f1), SvPV_nolen(f2)) == 0)) + g_strcmp0(SvPV_nolen(f1), SvPV_nolen(f2)) == 0)) static void perl_signal_remove_list(GSList **list, SV *func) { From ef0877f4849a73ba43e886a9faafb321d3559e43 Mon Sep 17 00:00:00 2001 From: dequis Date: Tue, 7 Apr 2015 23:01:09 -0300 Subject: [PATCH 0078/1650] Define g_strcmp0 to strcmp if the glib version is older than 2.16 --- src/common.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common.h b/src/common.h index bb246962..23d091a1 100644 --- a/src/common.h +++ b/src/common.h @@ -52,6 +52,10 @@ #define g_slice_free(type, mem) g_free(mem) #endif +#if !GLIB_CHECK_VERSION(2,16,0) +#define g_strcmp0(str1, str2) strcmp(str1, str2) +#endif + #ifdef USE_GC # define g_free(x) G_STMT_START { (x) = NULL; } G_STMT_END #endif From 9890daca797b31d34d97d953c512378aabe3d51f Mon Sep 17 00:00:00 2001 From: dequis Date: Sat, 11 Apr 2015 15:09:49 -0300 Subject: [PATCH 0079/1650] Handle nulls properly in the g_strcmp0() for glib<2.16 I wrote some tests to compare the behavior but I don't know where to put them, so i'm including them here: assert(g_strcmp0("a", "b") == -1); assert(g_strcmp0(NULL, "a") == -1); assert(g_strcmp0("a", NULL) == 1); assert(g_strcmp0("b", "a") == 1); assert(g_strcmp0("a", "a") == 0); assert(g_strcmp0(NULL, NULL) == 0); --- src/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.h b/src/common.h index 23d091a1..1b99753b 100644 --- a/src/common.h +++ b/src/common.h @@ -53,7 +53,7 @@ #endif #if !GLIB_CHECK_VERSION(2,16,0) -#define g_strcmp0(str1, str2) strcmp(str1, str2) +#define g_strcmp0(a, b) (!a ? -(a != b) : (!b ? (a != b) : strcmp(a, b))) #endif #ifdef USE_GC From 50e955e342c02ac55c48d5be71a940596ff72ac8 Mon Sep 17 00:00:00 2001 From: Haw Loeung Date: Tue, 14 Apr 2015 18:07:35 +1000 Subject: [PATCH 0080/1650] ssl: Add option to specify SSL cipher suite preference. --- docs/help/in/connect.in | 1 + docs/help/in/server.in | 1 + src/core/chat-commands.c | 6 +++++- src/core/network-openssl.c | 2 ++ src/core/server-connect-rec.h | 1 + src/core/server-setup-rec.h | 1 + src/core/servers-reconnect.c | 1 + src/core/servers-setup.c | 5 +++++ src/core/servers.c | 1 + src/core/session.c | 1 + src/fe-common/core/fe-server.c | 6 +++++- src/fe-common/irc/fe-irc-server.c | 3 +++ 12 files changed, 27 insertions(+), 2 deletions(-) diff --git a/docs/help/in/connect.in b/docs/help/in/connect.in index 3330966e..f13582cc 100644 --- a/docs/help/in/connect.in +++ b/docs/help/in/connect.in @@ -15,6 +15,7 @@ -ssl_verify: Verifies the SSL certificate of the server. -ssl_cafile: The file with the list of CA certificates. -ssl_capath: The directory which contains the CA certificates. + -ssl_ciphers: SSL cipher suite preference lists -noproxy: Ignores the global proxy configuration. -network: The network this connection belongs to. -host: The hostname you would like to connect from. diff --git a/docs/help/in/server.in b/docs/help/in/server.in index f6706daf..34c31972 100644 --- a/docs/help/in/server.in +++ b/docs/help/in/server.in @@ -22,6 +22,7 @@ -ssl_verify: Verifies the SSL certificate of the server. -ssl_cafile: The file with the list of CA certificates. -ssl_capath: The directory which contains the CA certificates. + -ssl_ciphers: SSL cipher suite preference lists -auto: Automatically connects to the server on startup. -noauto: Doesn't connect to the server on startup. -network: The network the server belongs to. diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 8d1ac3eb..3ee7beca 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -106,6 +106,8 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, conn->ssl_cafile = g_strdup(tmp); if ((tmp = g_hash_table_lookup(optlist, "ssl_capath")) != NULL) conn->ssl_capath = g_strdup(tmp); + if ((tmp = g_hash_table_lookup(optlist, "ssl_ciphers")) != NULL) + conn->ssl_ciphers = g_strdup(tmp); if ((conn->ssl_capath != NULL && conn->ssl_capath[0] != '\0') || (conn->ssl_cafile != NULL && conn->ssl_cafile[0] != '\0')) conn->ssl_verify = TRUE; @@ -138,6 +140,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, /* SYNTAX: CONNECT [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] + [-ssl_ciphers ] [-!] [-noautosendcmd] [-noproxy] [-network ] [-host ] [-rawlog ] @@ -244,6 +247,7 @@ static void sig_default_command_server(const char *data, SERVER_REC *server, /* SYNTAX: SERVER [-4 | -6] [-ssl] [-ssl_cert ] [-ssl_pkey ] [-ssl_pass ] [-ssl_verify] [-ssl_cafile ] [-ssl_capath ] + [-ssl_ciphers ] [-!] [-noautosendcmd] [-noproxy] [-network ] [-host ] [-rawlog ] @@ -483,7 +487,7 @@ void chat_commands_init(void) signal_add("default command server", (SIGNAL_FUNC) sig_default_command_server); signal_add("server sendmsg", (SIGNAL_FUNC) sig_server_sendmsg); - command_set_options("connect", "4 6 !! -network ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +host noproxy -rawlog noautosendcmd"); + command_set_options("connect", "4 6 !! -network ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +ssl_ciphers +host noproxy -rawlog noautosendcmd"); command_set_options("msg", "channel nick"); } diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index dcd857d8..e55f2ace 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -460,6 +460,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ const char *mypass = server->connrec->ssl_pass; const char *cafile = server->connrec->ssl_cafile; const char *capath = server->connrec->ssl_capath; + const char *ciphers = server->connrec->ssl_ciphers; gboolean verify = server->connrec->ssl_verify; g_return_val_if_fail(handle != NULL, NULL); @@ -478,6 +479,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); SSL_CTX_set_default_passwd_cb(ctx, get_pem_password_callback); SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)mypass); + SSL_CTX_set_cipher_list(ctx, ciphers); if (mycert && *mycert) { char *scert = NULL, *spkey = NULL; diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h index 17537508..80c5761b 100644 --- a/src/core/server-connect-rec.h +++ b/src/core/server-connect-rec.h @@ -28,6 +28,7 @@ char *ssl_pkey; char *ssl_pass; char *ssl_cafile; char *ssl_capath; +char *ssl_ciphers; GIOChannel *connect_handle; /* connect using this handle */ diff --git a/src/core/server-setup-rec.h b/src/core/server-setup-rec.h index ae797559..ecdde3f3 100644 --- a/src/core/server-setup-rec.h +++ b/src/core/server-setup-rec.h @@ -13,6 +13,7 @@ char *ssl_pkey; char *ssl_pass; char *ssl_cafile; char *ssl_capath; +char *ssl_ciphers; char *own_host; /* address to use when connecting this server */ IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */ diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index d99a5405..f9f82a13 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -197,6 +197,7 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info) dest->ssl_verify = src->ssl_verify; dest->ssl_cafile = g_strdup(src->ssl_cafile); dest->ssl_capath = g_strdup(src->ssl_capath); + dest->ssl_ciphers = g_strdup(src->ssl_ciphers); return dest; } diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 27d9f1f0..6cf48300 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -179,6 +179,8 @@ static void server_setup_fill_server(SERVER_CONNECT_REC *conn, conn->ssl_cafile = g_strdup(sserver->ssl_cafile); if (conn->ssl_capath == NULL && sserver->ssl_capath != NULL && sserver->ssl_capath[0] != '\0') conn->ssl_capath = g_strdup(sserver->ssl_capath); + if (conn->ssl_ciphers == NULL && sserver->ssl_ciphers != NULL && sserver->ssl_ciphers[0] != '\0') + conn->ssl_ciphers = g_strdup(sserver->ssl_ciphers); server_setup_fill_reconn(conn, sserver); @@ -405,6 +407,7 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node) rec->ssl_verify = config_node_get_bool(node, "ssl_verify", FALSE); rec->ssl_cafile = g_strdup(config_node_get_str(node, "ssl_cafile", NULL)); rec->ssl_capath = g_strdup(config_node_get_str(node, "ssl_capath", NULL)); + rec->ssl_ciphers = g_strdup(config_node_get_str(node, "ssl_ciphers", NULL)); if (rec->ssl_cafile || rec->ssl_capath) rec->ssl_verify = TRUE; if (rec->ssl_cert != NULL || rec->ssl_verify) @@ -445,6 +448,7 @@ static void server_setup_save(SERVER_SETUP_REC *rec) iconfig_node_set_bool(node, "ssl_verify", rec->ssl_verify); iconfig_node_set_str(node, "ssl_cafile", rec->ssl_cafile); iconfig_node_set_str(node, "ssl_capath", rec->ssl_capath); + iconfig_node_set_str(node, "ssl_ciphers", rec->ssl_ciphers); iconfig_node_set_str(node, "own_host", rec->own_host); iconfig_node_set_str(node, "family", @@ -486,6 +490,7 @@ static void server_setup_destroy(SERVER_SETUP_REC *rec) g_free_not_null(rec->ssl_pass); g_free_not_null(rec->ssl_cafile); g_free_not_null(rec->ssl_capath); + g_free_not_null(rec->ssl_ciphers); g_free(rec->address); g_free(rec); } diff --git a/src/core/servers.c b/src/core/servers.c index 6eaad191..3342304e 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -636,6 +636,7 @@ void server_connect_unref(SERVER_CONNECT_REC *conn) g_free_not_null(conn->ssl_pass); g_free_not_null(conn->ssl_cafile); g_free_not_null(conn->ssl_capath); + g_free_not_null(conn->ssl_ciphers); g_free_not_null(conn->channels); g_free_not_null(conn->away_reason); diff --git a/src/core/session.c b/src/core/session.c index b3002632..e49162b2 100644 --- a/src/core/session.c +++ b/src/core/session.c @@ -165,6 +165,7 @@ static void session_save_server(SERVER_REC *server, CONFIG_REC *config, config_node_set_bool(config, node, "ssl_verify", server->connrec->ssl_verify); config_node_set_str(config, node, "ssl_cafile", server->connrec->ssl_cafile); config_node_set_str(config, node, "ssl_capath", server->connrec->ssl_capath); + config_node_set_str(config, node, "ssl_ciphers", server->connrec->ssl_ciphers); handle = g_io_channel_unix_get_fd(net_sendbuffer_handle(server->handle)); config_node_set_int(config, node, "handle", handle); diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index 2dec1d8a..ec9b5e4c 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -173,6 +173,10 @@ static void cmd_server_add(const char *data) if (value != NULL && *value != '\0') rec->ssl_capath = g_strdup(value); + value = g_hash_table_lookup(optlist, "ssl_ciphers"); + if (value != NULL && *value != '\0') + rec->ssl_ciphers = g_strdup(value); + if ((rec->ssl_cafile != NULL && rec->ssl_cafile[0] != '\0') || (rec->ssl_capath != NULL && rec->ssl_capath[0] != '\0')) rec->ssl_verify = TRUE; @@ -387,7 +391,7 @@ void fe_server_init(void) 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); - command_set_options("server add", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath auto noauto proxy noproxy -host -port noautosendcmd"); + 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"); 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-irc-server.c b/src/fe-common/irc/fe-irc-server.c index abde1112..2cb99a2f 100644 --- a/src/fe-common/irc/fe-irc-server.c +++ b/src/fe-common/irc/fe-irc-server.c @@ -52,6 +52,7 @@ const char *get_visible_target(IRC_SERVER_REC *server, const char *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 ]
[ []] */ @@ -121,6 +122,8 @@ static void cmd_server_list(const char *data) g_string_append_printf(str, "ssl_cafile: %s, ", rec->ssl_cafile); if (rec->ssl_capath) g_string_append_printf(str, "ssl_capath: %s, ", rec->ssl_capath); + if (rec->ssl_ciphers) + g_string_append_printf(str, "ssl_ciphers: %s, ", rec->ssl_ciphers); } if (rec->max_cmds_at_once > 0) From 349ed35ce099d9003078e000acf5d95b5fd644e8 Mon Sep 17 00:00:00 2001 From: Haw Loeung Date: Wed, 15 Apr 2015 00:44:07 +1000 Subject: [PATCH 0081/1650] ssl: Fixed call to SSL_CTX_set_cipher_list() only when ssl_ciphers specified and warn when no cipher suite could be selected. --- src/core/network-openssl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index e55f2ace..465c4154 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -479,7 +479,10 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); SSL_CTX_set_default_passwd_cb(ctx, get_pem_password_callback); SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)mypass); - SSL_CTX_set_cipher_list(ctx, ciphers); + if (ciphers && *ciphers) { + if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) + g_warning("No valid SSL cipher suite could be selected"); + } if (mycert && *mycert) { char *scert = NULL, *spkey = NULL; From 9f77dd802dfe63b79c0d82d4b9ecc0974e354a59 Mon Sep 17 00:00:00 2001 From: Haw Loeung Date: Sat, 18 Apr 2015 13:53:07 +1000 Subject: [PATCH 0082/1650] trivial: Minor cosmetic changes fixing docs as per review from ahf. --- docs/help/in/connect.in | 2 +- docs/help/in/server.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/help/in/connect.in b/docs/help/in/connect.in index f13582cc..df50d1b9 100644 --- a/docs/help/in/connect.in +++ b/docs/help/in/connect.in @@ -15,7 +15,7 @@ -ssl_verify: Verifies the SSL certificate of the server. -ssl_cafile: The file with the list of CA certificates. -ssl_capath: The directory which contains the CA certificates. - -ssl_ciphers: SSL cipher suite preference lists + -ssl_ciphers: SSL cipher suite preference lists. -noproxy: Ignores the global proxy configuration. -network: The network this connection belongs to. -host: The hostname you would like to connect from. diff --git a/docs/help/in/server.in b/docs/help/in/server.in index 34c31972..e407b6a9 100644 --- a/docs/help/in/server.in +++ b/docs/help/in/server.in @@ -22,7 +22,7 @@ -ssl_verify: Verifies the SSL certificate of the server. -ssl_cafile: The file with the list of CA certificates. -ssl_capath: The directory which contains the CA certificates. - -ssl_ciphers: SSL cipher suite preference lists + -ssl_ciphers: SSL cipher suite preference lists. -auto: Automatically connects to the server on startup. -noauto: Doesn't connect to the server on startup. -network: The network the server belongs to. From 6b56f098e941563258a9a7fb207f1df6de7cbb11 Mon Sep 17 00:00:00 2001 From: Peder Stray Date: Sun, 19 Apr 2015 13:14:54 +0200 Subject: [PATCH 0083/1650] Change g_hash_table_contains() for compatibility with glib < 2.32 --- src/lib-config/get.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib-config/get.c b/src/lib-config/get.c index 53d744da..a83686fd 100644 --- a/src/lib-config/get.c +++ b/src/lib-config/get.c @@ -68,7 +68,7 @@ CONFIG_NODE *config_node_section_index(CONFIG_REC *rec, CONFIG_NODE *parent, con config_node_remove(rec, parent, node); node = NULL; show_error = 1; - } else if (!g_hash_table_contains(rec->cache_nodes, node)) { + } else if (!g_hash_table_lookup_extended(rec->cache_nodes, node, NULL, NULL)) { g_hash_table_insert(rec->cache_nodes, node, NULL); show_error = 1; } From 2d7030a84445ee4547af43970cfb252b36246e62 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 12 Feb 2015 00:07:22 +0100 Subject: [PATCH 0084/1650] Implement support for IRCv3.1 CAP negotiation --- docs/signals.txt | 5 ++ src/core/misc.c | 24 ++++++ src/core/misc.h | 3 + src/irc/core/Makefile.am | 2 + src/irc/core/irc-cap.c | 172 +++++++++++++++++++++++++++++++++++++ src/irc/core/irc-cap.h | 9 ++ src/irc/core/irc-core.c | 3 + src/irc/core/irc-servers.c | 14 ++- src/irc/core/irc-servers.h | 7 ++ 9 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 src/irc/core/irc-cap.c create mode 100644 src/irc/core/irc-cap.h diff --git a/docs/signals.txt b/docs/signals.txt index f0860d3e..45658b79 100644 --- a/docs/signals.txt +++ b/docs/signals.txt @@ -131,6 +131,11 @@ irc-nicklist.c: irc-servers.c: "event connected", SERVER_REC +irc-cap.c + "server cap ack ", SERVER_REC + "server cap nak ", SERVER_REC + "server cap end", SERVER_REC + irc.c: "server event", SERVER_REC, char *data, char *sender_nick, char *sender_address diff --git a/src/core/misc.c b/src/core/misc.c index ef8501d5..395e47ad 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -211,6 +211,30 @@ void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, const void *data return NULL; } +void gslist_free_full (GSList *list, GDestroyNotify free_func) +{ + GSList *tmp; + + if (!list) + return; + + for (tmp = list; tmp != NULL; tmp = tmp->next) + free_func(tmp->data); + + g_slist_free(list); +} + +GSList *gslist_remove_string (GSList *list, const char *str) +{ + GSList *l; + + l = g_slist_find_custom(list, str, (GCompareFunc) g_strcmp0); + if (l != NULL) + return g_slist_remove_link(list, l); + + return list; +} + /* `list' contains pointer to structure with a char* to string. */ char *gslistptr_to_string(GSList *list, int offset, const char *delimiter) { diff --git a/src/core/misc.h b/src/core/misc.h index c6369489..7e78d3b9 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -21,6 +21,9 @@ GSList *gslist_find_string(GSList *list, const char *key); GSList *gslist_find_icase_string(GSList *list, const char *key); GList *glist_find_string(GList *list, const char *key); GList *glist_find_icase_string(GList *list, const char *key); +GSList *gslist_remove_string (GSList *list, const char *str); + +void gslist_free_full (GSList *list, GDestroyNotify free_func); void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, const void *data); diff --git a/src/irc/core/Makefile.am b/src/irc/core/Makefile.am index 3db5cf0e..7d885d20 100644 --- a/src/irc/core/Makefile.am +++ b/src/irc/core/Makefile.am @@ -26,6 +26,7 @@ libirc_core_a_SOURCES = \ irc-servers-reconnect.c \ irc-servers-setup.c \ irc-session.c \ + irc-cap.c \ lag.c \ massjoin.c \ modes.c \ @@ -48,6 +49,7 @@ pkginc_irc_core_HEADERS = \ irc-queries.h \ irc-servers.h \ irc-servers-setup.h \ + irc-cap.h \ modes.h \ mode-lists.h \ module.h \ diff --git a/src/irc/core/irc-cap.c b/src/irc/core/irc-cap.c new file mode 100644 index 00000000..c5bf4e67 --- /dev/null +++ b/src/irc/core/irc-cap.c @@ -0,0 +1,172 @@ +#include "module.h" +#include "signals.h" +#include "misc.h" + +#include "irc-cap.h" +#include "irc-servers.h" + +int cap_toggle (IRC_SERVER_REC *server, char *cap, int enable) +{ + if (cap == NULL || *cap == '\0') + return FALSE; + + /* If the negotiation hasn't been completed yet just queue the requests */ + if (!server->cap_complete) { + if (enable && !gslist_find_string(server->cap_queue, cap)) { + server->cap_queue = g_slist_prepend(server->cap_queue, g_strdup(cap)); + return TRUE; + } + else if (!enable && gslist_find_string(server->cap_queue, cap)) { + server->cap_queue = gslist_remove_string(server->cap_queue, cap); + return TRUE; + } + + return FALSE; + } + + if (enable && !gslist_find_string(server->cap_active, cap)) { + /* Make sure the required cap is supported by the server */ + if (!gslist_find_string(server->cap_supported, cap)) + return FALSE; + + irc_send_cmdv(server, "CAP REQ %s", cap); + return TRUE; + } + else if (!enable && gslist_find_string(server->cap_active, cap)) { + irc_send_cmdv(server, "CAP REQ -%s", cap); + return TRUE; + } + + return FALSE; +} + +void cap_finish_negotiation (IRC_SERVER_REC *server) +{ + if (server->cap_complete) + return; + + server->cap_complete = TRUE; + irc_send_cmd_now(server, "CAP END"); + + signal_emit("server cap end", 1, server); +} + +static void cap_emit_signal (IRC_SERVER_REC *server, char *cmd, char *args) +{ + char *signal_name; + + signal_name = g_strdup_printf("server cap %s %s", cmd, args? args: ""); + signal_emit(signal_name, 1, server); + g_free(signal_name); +} + +static void event_cap (IRC_SERVER_REC *server, char *args, char *nick, char *address) +{ + GSList *tmp; + GString *cmd; + char *params, *evt, *list, **caps; + int i, caps_length, disable, avail_caps; + + params = event_get_params(args, 3, NULL, &evt, &list); + if (params == NULL) + return; + + /* Strip the trailing whitespaces before splitting the string, some servers send responses with + * superfluous whitespaces that g_strsplit the interprets as tokens */ + caps = g_strsplit(g_strchomp(list), " ", -1); + caps_length = g_strv_length(caps); + + if (!g_strcmp0(evt, "LS")) { + /* Create a list of the supported caps */ + for (i = 0; i < caps_length; i++) + server->cap_supported = g_slist_prepend(server->cap_supported, g_strdup(caps[i])); + + /* Request the required caps, if any */ + if (server->cap_queue == NULL) { + cap_finish_negotiation(server); + } + else { + cmd = g_string_new("CAP REQ :"); + + avail_caps = 0; + + /* Check whether the cap is supported by the server */ + for (tmp = server->cap_queue; tmp != NULL; tmp = tmp->next) { + if (gslist_find_string(server->cap_supported, tmp->data)) { + g_string_append_c(cmd, ' '); + g_string_append(cmd, tmp->data); + + avail_caps++; + } + } + + /* Clear the queue here */ + gslist_free_full(server->cap_queue, (GDestroyNotify) g_free); + server->cap_queue = NULL; + + /* If the server doesn't support any cap we requested close the negotiation here */ + if (avail_caps > 0) + irc_send_cmd_now(server, cmd->str); + else + cap_finish_negotiation(server); + + g_string_free(cmd, TRUE); + } + } + else if (!g_strcmp0(evt, "ACK")) { + int got_sasl = FALSE; + + /* Emit a signal for every ack'd cap */ + for (i = 0; i < caps_length; i++) { + disable = (*caps[i] == '-'); + + if (disable) + server->cap_active = gslist_remove_string(server->cap_active, caps[i] + 1); + else + server->cap_active = g_slist_prepend(server->cap_active, g_strdup(caps[i])); + + if (!g_strcmp0(caps[i], "sasl")) + got_sasl = TRUE; + + cap_emit_signal(server, "ack", caps[i]); + } + + /* Hopefully the server has ack'd all the caps requested and we're ready to terminate the + * negotiation, unless sasl was requested. In this case we must not terminate the negotiation + * until the sasl handshake is over. */ + if (got_sasl == FALSE) + cap_finish_negotiation(server); + } + else if (!g_strcmp0(evt, "NAK")) { + g_warning("The server answered with a NAK to our CAP request, this should not happen"); + + /* A NAK'd request means that a required cap can't be enabled or disabled, don't update the + * list of active caps and notify the listeners. */ + for (i = 0; i < caps_length; i++) + cap_emit_signal(server, "nak", caps[i]); + } + + g_strfreev(caps); + g_free(params); +} + +static void event_invalid_cap (IRC_SERVER_REC *server, const char *data, const char *from) +{ + /* The server didn't understand one (or more) requested caps, terminate the negotiation. + * This could be handled in a graceful way but since it shouldn't really ever happen this seems a + * good way to deal with 410 errors. */ + server->cap_complete = FALSE; + irc_send_cmd_now(server, "CAP END"); +} + +void cap_init (void) +{ + signal_add_first("event cap", (SIGNAL_FUNC) event_cap); + signal_add_first("event 410", (SIGNAL_FUNC) event_invalid_cap); +} + +void cap_deinit (void) +{ + signal_remove("event cap", (SIGNAL_FUNC) event_cap); + signal_remove("event 410", (SIGNAL_FUNC) event_invalid_cap); +} diff --git a/src/irc/core/irc-cap.h b/src/irc/core/irc-cap.h new file mode 100644 index 00000000..df957cd2 --- /dev/null +++ b/src/irc/core/irc-cap.h @@ -0,0 +1,9 @@ +#ifndef __IRC_CAP_H +#define __IRC_CAP_H + +void cap_init(void); +void cap_deinit(void); +int cap_toggle (IRC_SERVER_REC *server, char *cap, int enable); +void cap_finish_negotiation (IRC_SERVER_REC *server); + +#endif diff --git a/src/irc/core/irc-core.c b/src/irc/core/irc-core.c index bf7386ad..e3ceeeef 100644 --- a/src/irc/core/irc-core.c +++ b/src/irc/core/irc-core.c @@ -26,6 +26,7 @@ #include "irc-chatnets.h" #include "irc-channels.h" #include "irc-queries.h" +#include "irc-cap.h" #include "irc-servers-setup.h" #include "channels-setup.h" @@ -117,6 +118,7 @@ void irc_core_init(void) lag_init(); netsplit_init(); irc_expandos_init(); + cap_init(); settings_check(); module_register("core", "irc"); @@ -126,6 +128,7 @@ void irc_core_deinit(void) { signal_emit("chat protocol deinit", 1, chat_protocol_find("IRC")); + cap_deinit(); irc_expandos_deinit(); netsplit_deinit(); lag_deinit(); diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index d7122eae..335c88ef 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -32,6 +32,7 @@ #include "irc-queries.h" #include "irc-servers-setup.h" #include "irc-servers.h" +#include "irc-cap.h" #include "channel-rejoin.h" #include "servers-idle.h" #include "servers-reconnect.h" @@ -201,6 +202,8 @@ static void server_init(IRC_SERVER_REC *server) conn = server->connrec; + irc_send_cmd_now(server, "CAP LS"); + if (conn->proxy != NULL && conn->proxy_password != NULL && *conn->proxy_password != '\0') { cmd = g_strdup_printf("PASS %s", conn->proxy_password); @@ -409,7 +412,16 @@ static void sig_disconnected(IRC_SERVER_REC *server) server_redirect_destroy(tmp->next->data); } g_slist_free(server->cmdqueue); - server->cmdqueue = NULL; + server->cmdqueue = NULL; + + gslist_free_full(server->cap_active, (GDestroyNotify) g_free); + server->cap_active = NULL; + + gslist_free_full(server->cap_supported, (GDestroyNotify) g_free); + server->cap_supported = NULL; + + gslist_free_full(server->cap_queue, (GDestroyNotify) g_free); + server->cap_queue = NULL; /* these are dynamically allocated only if isupport was sent */ g_hash_table_foreach(server->isupport, diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h index 7e4eeabf..f809fab5 100644 --- a/src/irc/core/irc-servers.h +++ b/src/irc/core/irc-servers.h @@ -69,6 +69,13 @@ struct _IRC_SERVER_REC { int max_whois_in_cmd; /* max. number of nicks in one /WHOIS command */ int max_msgs_in_cmd; /* max. number of targets in one /MSG */ + GSList *cap_supported; /* A list of caps supported by the server */ + GSList *cap_active; /* A list of caps active for this session */ + GSList *cap_queue; /* A list of caps to request on connection */ + int cap_complete:1; /* We've done the initial CAP negotiation */ + + guint sasl_timeout; /* Holds the source id of the running timeout */ + /* Command sending queue */ int cmdcount; /* number of commands in `cmdqueue'. Can be more than there actually is, to make flood control remember From ae742f3f13f0d941f3a099740afddcb9d73c446b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Szczepa=C5=84ski?= Date: Thu, 14 May 2015 13:06:50 +0100 Subject: [PATCH 0085/1650] lastlog doc fix Only the filename can come right after `-file`. Having `-force` in that position causes an `Irssi: Could not open lastlog: No such file or directory` error. --- docs/help/in/lastlog.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/help/in/lastlog.in b/docs/help/in/lastlog.in index 25879d31..e96e2ed5 100644 --- a/docs/help/in/lastlog.in +++ b/docs/help/in/lastlog.in @@ -35,7 +35,7 @@ /LASTLOG holiday /LASTLOG 'is on vacation' 10 - /LASTLOG -file -force ~/mike.log 'mike' + /LASTLOG -force -file ~/mike.log 'mike' /LASTLOG -hilight /LASTLOG -5 searchterm From 16c71cf1fbc1e7987fdde821813005b87237e951 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 15 May 2015 16:42:51 +0200 Subject: [PATCH 0086/1650] Implement CHANTYPES support --- src/core/servers.h | 2 +- src/fe-common/irc/dcc/fe-dcc-chat.c | 2 +- src/fe-common/irc/dcc/fe-dcc-get.c | 5 +++-- src/fe-common/irc/fe-ctcp.c | 8 ++++---- src/fe-common/irc/fe-events-numeric.c | 4 ++-- src/fe-common/irc/fe-events.c | 6 +++--- src/fe-common/irc/fe-irc-channels.c | 2 +- src/fe-common/irc/fe-irc-messages.c | 20 ++++++++++---------- src/fe-common/irc/fe-irc-queries.c | 2 +- src/fe-common/irc/fe-modes.c | 2 +- src/fe-common/irc/fe-netjoin.c | 2 +- src/irc/core/bans.c | 2 +- src/irc/core/channel-rejoin.c | 2 +- src/irc/core/irc-channels.c | 4 ++-- src/irc/core/irc-commands.c | 2 +- src/irc/core/irc-nicklist.c | 2 +- src/irc/core/irc-queries.c | 4 ++-- src/irc/core/irc-servers.c | 21 ++++++++++++++------- src/irc/core/irc.h | 6 ------ src/irc/core/modes.c | 6 +++--- src/irc/dcc/dcc-autoget.c | 2 +- src/irc/flood/flood.c | 4 ++-- src/irc/proxy/listen.c | 2 +- 23 files changed, 57 insertions(+), 55 deletions(-) diff --git a/src/core/servers.h b/src/core/servers.h index d6afbdf5..f39c650b 100644 --- a/src/core/servers.h +++ b/src/core/servers.h @@ -18,7 +18,7 @@ (SERVER_CONNECT(conn) ? TRUE : FALSE) #define server_ischannel(server, channel) \ - (server)->ischannel(server, channel) + ((server)->ischannel(server, channel)) /* all strings should be either NULL or dynamically allocated */ /* address and nick are mandatory, rest are optional */ diff --git a/src/fe-common/irc/dcc/fe-dcc-chat.c b/src/fe-common/irc/dcc/fe-dcc-chat.c index e2706ba3..5bcb3475 100644 --- a/src/fe-common/irc/dcc/fe-dcc-chat.c +++ b/src/fe-common/irc/dcc/fe-dcc-chat.c @@ -44,7 +44,7 @@ static void dcc_request(CHAT_DCC_REC *dcc) if (!IS_DCC_CHAT(dcc)) return; printformat(dcc->server, NULL, MSGLEVEL_DCC, - ischannel(*dcc->target) ? IRCTXT_DCC_CHAT_CHANNEL : + server_ischannel(SERVER(dcc->server), dcc->target) ? IRCTXT_DCC_CHAT_CHANNEL : IRCTXT_DCC_CHAT, dcc->id, dcc->addrstr, dcc->port, dcc->target); } diff --git a/src/fe-common/irc/dcc/fe-dcc-get.c b/src/fe-common/irc/dcc/fe-dcc-get.c index 451463f9..675cab65 100644 --- a/src/fe-common/irc/dcc/fe-dcc-get.c +++ b/src/fe-common/irc/dcc/fe-dcc-get.c @@ -21,6 +21,7 @@ #include "module.h" #include "signals.h" #include "levels.h" +#include "servers.h" #include "irc.h" #include "dcc-file.h" @@ -35,12 +36,12 @@ static void dcc_request(GET_DCC_REC *dcc) { char *sizestr; - if (!IS_DCC_GET(dcc)) return; + if (!IS_DCC_GET(dcc)) return; sizestr = dcc_get_size_str(dcc->size); printformat(dcc->server, NULL, MSGLEVEL_DCC, - ischannel(*dcc->target) ? IRCTXT_DCC_SEND_CHANNEL : + server_ischannel(SERVER(dcc->server), dcc->target) ? IRCTXT_DCC_SEND_CHANNEL : IRCTXT_DCC_SEND, dcc->nick, dcc->addrstr, dcc->port, dcc->arg, sizestr, dcc->target); diff --git a/src/fe-common/irc/fe-ctcp.c b/src/fe-common/irc/fe-ctcp.c index 2321bb7a..cbb591ba 100644 --- a/src/fe-common/irc/fe-ctcp.c +++ b/src/fe-common/irc/fe-ctcp.c @@ -49,7 +49,7 @@ static void ctcp_default_msg(IRC_SERVER_REC *server, const char *data, data = p+1; } - printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS, + printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS, IRCTXT_CTCP_REQUESTED_UNKNOWN, nick, addr, cmd, data, target); g_free(cmd); @@ -113,8 +113,8 @@ static void ctcp_default_reply(IRC_SERVER_REC *server, const char *data, ctcpdata = ptr+1; } - printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS, - ischannel(*target) ? IRCTXT_CTCP_REPLY_CHANNEL : + printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS, + server_ischannel(SERVER(server), target) ? IRCTXT_CTCP_REPLY_CHANNEL : IRCTXT_CTCP_REPLY, ctcp, nick, ctcpdata, target); g_free(ctcp); } @@ -137,7 +137,7 @@ static void ctcp_ping_reply(IRC_SERVER_REC *server, const char *data, g_get_current_time(&tv); usecs = get_timeval_diff(&tv, &tv2); - printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS, + printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS, IRCTXT_CTCP_PING_REPLY, nick, usecs/1000, usecs%1000); } diff --git a/src/fe-common/irc/fe-events-numeric.c b/src/fe-common/irc/fe-events-numeric.c index ec7669ab..3eb124fc 100644 --- a/src/fe-common/irc/fe-events-numeric.c +++ b/src/fe-common/irc/fe-events-numeric.c @@ -400,7 +400,7 @@ static void event_target_unavailable(IRC_SERVER_REC *server, const char *data, g_return_if_fail(data != NULL); params = event_get_params(data, 2, NULL, &target); - if (!ischannel(*target)) { + if (!server_ischannel(SERVER(server), target)) { /* nick unavailable */ printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NICK_UNAVAILABLE, target); @@ -583,7 +583,7 @@ static void print_event_received(IRC_SERVER_REC *server, const char *data, return; ptr++; - if (ischannel(*data)) /* directed at channel */ + if (server_ischannel(SERVER(server), data)) /* directed at channel */ target = g_strndup(data, (int)(ptr - data - 1)); else if (!target_param || *ptr == ':' || (ptr2 = strchr(ptr, ' ')) == NULL) target = NULL; diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c index 5cde9e4b..ad5e7559 100644 --- a/src/fe-common/irc/fe-events.c +++ b/src/fe-common/irc/fe-events.c @@ -52,15 +52,15 @@ static void event_privmsg(IRC_SERVER_REC *server, const char *data, params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); if (nick == NULL) nick = server->real_address; if (addr == NULL) addr = ""; - if (*target == '@' && ischannel(target[1])) { + if (*target == '@' && server_ischannel(SERVER(server), &target[1])) { /* Hybrid 6 feature, send msg to all ops in channel */ recoded = recode_in(SERVER(server), msg, target+1); signal_emit("message irc op_public", 5, server, recoded, nick, addr, get_visible_target(server, target+1)); } else { - recoded = recode_in(SERVER(server), msg, ischannel(*target) ? target : nick); - signal_emit(ischannel(*target) ? + recoded = recode_in(SERVER(server), msg, server_ischannel(SERVER(server), target) ? target : nick); + signal_emit(server_ischannel(SERVER(server), target) ? "message public" : "message private", 5, server, recoded, nick, addr, get_visible_target(server, target)); diff --git a/src/fe-common/irc/fe-irc-channels.c b/src/fe-common/irc/fe-irc-channels.c index e884aef4..9129e451 100644 --- a/src/fe-common/irc/fe-irc-channels.c +++ b/src/fe-common/irc/fe-irc-channels.c @@ -46,7 +46,7 @@ static void sig_event_forward(SERVER_REC *server, const char *data, char *params, *from, *to; params = event_get_params(data, 3, NULL, &from, &to); - if (from != NULL && to != NULL && ischannel(*from) && ischannel(*to)) { + if (from != NULL && to != NULL && server_ischannel(server, *from) && server_ischannel(server, *to)) { channel = irc_channel_find(server, from); if (channel != NULL && irc_channel_find(server, to) == NULL) { window_bind_add(window_item_window(channel), diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index 94d1ad4a..780c0b7e 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -57,7 +57,7 @@ static const char *skip_target(IRC_SERVER_REC *server, const char *target) break; }; - if(ischannel(target[i])) + if(server_ischannel(SERVER(server), &target[i])) target += i; return target; @@ -136,7 +136,7 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg, oldtarget = target; target = skip_target(IRC_SERVER(server), target); - if (ischannel(*target)) + if (server_ischannel(SERVER(server), target)) item = irc_channel_find(server, target); else item = irc_query_find(server, target); @@ -146,7 +146,7 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg, printformat(server, target, MSGLEVEL_ACTIONS | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT | - (ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS), + (server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS), item != NULL && oldtarget == target ? IRCTXT_OWN_ACTION : IRCTXT_OWN_ACTION_TARGET, server->nick, msg, oldtarget); g_free_not_null(freemsg); @@ -166,7 +166,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, target = skip_target(IRC_SERVER(server), target); level = MSGLEVEL_ACTIONS | - (ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS); + (server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS); if (ignore_check(SERVER(server), nick, address, target, msg, level)) return; @@ -175,7 +175,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; - if (ischannel(*target)) { + if (server_ischannel(SERVER(server), target)) { item = irc_channel_find(server, target); } else { own = (!g_strcmp0(nick, server->nick)); @@ -185,7 +185,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, if (settings_get_bool("emphasis")) msg = freemsg = expand_emphasis(item, msg); - if (ischannel(*target)) { + if (server_ischannel(SERVER(server), target)) { /* channel action */ if (window_item_is_active(item) && target == oldtarget) { /* message to active channel in window */ @@ -245,16 +245,16 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg, } if (ignore_check(server, nick, address, - ischannel(*target) ? target : NULL, + server_ischannel(SERVER(server), target) ? target : NULL, msg, level)) return; if (ignore_check(server, nick, address, - ischannel(*target) ? target : NULL, + server_ischannel(SERVER(server), target) ? target : NULL, msg, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; - if (ischannel(*target)) { + if (server_ischannel(SERVER(server), target)) { /* notice in some channel */ printformat(server, target, level, IRCTXT_NOTICE_PUBLIC, nick, oldtarget, msg); @@ -283,7 +283,7 @@ static void sig_message_irc_ctcp(IRC_SERVER_REC *server, const char *cmd, oldtarget = target; target = skip_target(server, target); - printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS, + printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS, IRCTXT_CTCP_REQUESTED, nick, addr, cmd, data, oldtarget); } diff --git a/src/fe-common/irc/fe-irc-queries.c b/src/fe-common/irc/fe-irc-queries.c index 0861c9e4..b2faefbc 100644 --- a/src/fe-common/irc/fe-irc-queries.c +++ b/src/fe-common/irc/fe-irc-queries.c @@ -63,7 +63,7 @@ static void event_privmsg(SERVER_REC *server, const char *data, g_return_if_fail(data != NULL); - if (nick == NULL || address == NULL || ischannel(*data) || + if (nick == NULL || address == NULL || server_ischannel(server, data) || !settings_get_bool("query_track_nick_changes")) return; diff --git a/src/fe-common/irc/fe-modes.c b/src/fe-common/irc/fe-modes.c index e5317c0f..53e56c97 100644 --- a/src/fe-common/irc/fe-modes.c +++ b/src/fe-common/irc/fe-modes.c @@ -168,7 +168,7 @@ static void sig_message_mode(IRC_SERVER_REC *server, const char *channel, mode, MSGLEVEL_MODES)) return; - if (!ischannel(*channel)) { + if (!server_ischannel(SERVER(server), channel)) { /* user mode change */ printformat(server, NULL, MSGLEVEL_MODES, IRCTXT_USERMODE_CHANGE, mode, channel); diff --git a/src/fe-common/irc/fe-netjoin.c b/src/fe-common/irc/fe-netjoin.c index 35c463e4..f5cb081e 100644 --- a/src/fe-common/irc/fe-netjoin.c +++ b/src/fe-common/irc/fe-netjoin.c @@ -400,7 +400,7 @@ static void msg_mode(IRC_SERVER_REC *server, const char *channel, int show; g_return_if_fail(data != NULL); - if (!ischannel(*channel) || addr != NULL) + if (!server_ischannel(SERVER(server), channel) || addr != NULL) return; params = event_get_params(data, 2 | PARAM_FLAG_GETREST, diff --git a/src/irc/core/bans.c b/src/irc/core/bans.c index b60e681b..68dd45c0 100644 --- a/src/irc/core/bans.c +++ b/src/irc/core/bans.c @@ -186,7 +186,7 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server, if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channel, &nicks)) return; - if (!ischannel(*channel)) cmd_param_error(CMDERR_NOT_JOINED); + if (!server_ischannel(SERVER(server), channel)) cmd_param_error(CMDERR_NOT_JOINED); if (*nicks == '\0') { if (g_strcmp0(data, "*") != 0) cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); diff --git a/src/irc/core/channel-rejoin.c b/src/irc/core/channel-rejoin.c index 68a1dee1..154035ae 100644 --- a/src/irc/core/channel-rejoin.c +++ b/src/irc/core/channel-rejoin.c @@ -149,7 +149,7 @@ static void event_target_unavailable(IRC_SERVER_REC *server, const char *data) g_return_if_fail(data != NULL); params = event_get_params(data, 2, NULL, &channel); - if (ischannel(*channel)) { + if (server_ischannel(SERVER(server), channel)) { chanrec = irc_channel_find(server, channel); if (chanrec != NULL && chanrec->joined) { /* dalnet event - can't change nick while diff --git a/src/irc/core/irc-channels.c b/src/irc/core/irc-channels.c index e38cb98b..add18acf 100644 --- a/src/irc/core/irc-channels.c +++ b/src/irc/core/irc-channels.c @@ -99,7 +99,7 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data, tmp = chanlist; for (;; tmp++) { if (*tmp != NULL) { - channel = ischannel(**tmp) ? g_strdup(*tmp) : + channel = server_ischannel(SERVER(server), *tmp) ? g_strdup(*tmp) : g_strdup_printf("#%s", *tmp); chanrec = irc_channel_find(server, channel); @@ -134,7 +134,7 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data, if (use_keys) cmdlen += outkeys->len; if (*tmpstr != NULL) - cmdlen += ischannel(**tmpstr) ? strlen(*tmpstr) : + cmdlen += server_ischannel(SERVER(server), *tmpstr) ? strlen(*tmpstr) : strlen(*tmpstr)+1; if (*tmpkey != NULL) cmdlen += strlen(*tmpkey); diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index e7fb5067..f2cd49c0 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -191,7 +191,7 @@ static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item return; if (*channame == '\0' || *nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - if (!ischannel(*channame)) cmd_param_error(CMDERR_NOT_JOINED); + if (!server_ischannel(SERVER(server), channame)) cmd_param_error(CMDERR_NOT_JOINED); recoded = recode_out(SERVER(server), reason, channame); g_string_printf(tmpstr, "KICK %s %s :%s", channame, nicks, recoded); diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c index 5438509e..667016aa 100644 --- a/src/irc/core/irc-nicklist.c +++ b/src/irc/core/irc-nicklist.c @@ -394,7 +394,7 @@ static void event_target_unavailable(IRC_SERVER_REC *server, const char *data) g_return_if_fail(data != NULL); params = event_get_params(data, 2, NULL, &channel); - if (!ischannel(*channel)) { + if (!server_ischannel(SERVER(server), channel)) { /* nick is unavailable. */ event_nick_in_use(server, data); } diff --git a/src/irc/core/irc-queries.c b/src/irc/core/irc-queries.c index 72c17df1..12861744 100644 --- a/src/irc/core/irc-queries.c +++ b/src/irc/core/irc-queries.c @@ -60,8 +60,8 @@ static void check_query_changes(IRC_SERVER_REC *server, const char *nick, { QUERY_REC *query; - if (ischannel(*target)) - return; + if (server_ischannel(SERVER(server), target)) + return; query = irc_query_find(server, nick); if (query == NULL) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index d7122eae..c04c4318 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -71,13 +71,20 @@ static int isnickflag_func(SERVER_REC *server, char flag) static int ischannel_func(SERVER_REC *server, const char *data) { - if (*data == '@') { - /* @#channel, @+#channel */ - data++; - if (*data == '+' && ischannel(data[1])) - return 1; - } - return ischannel(*data); + IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server; + char *chantypes; + + chantypes = g_hash_table_lookup(irc_server->isupport, "chantypes"); + if (chantypes == NULL) + chantypes = "#&!+"; /* normal, local, secure, modeless */ + + /* @#channel, @+#channel */ + if (data[0] == '@' && data[1] == '+') + data += 2; + else if (data[0] == '@') + data += 1; + + return strchr(chantypes, *data) != NULL; } static char **split_line(const SERVER_REC *server, const char *line, diff --git a/src/irc/core/irc.h b/src/irc/core/irc.h index de19e084..b5bd833a 100644 --- a/src/irc/core/irc.h +++ b/src/irc/core/irc.h @@ -22,12 +22,6 @@ typedef struct _REDIRECT_REC REDIRECT_REC; #define isnickflag(server, a) \ (server->prefix[(int)(unsigned char) a] != '\0') -#define ischannel(a) \ - ((a) == '#' || /* normal */ \ - (a) == '&' || /* local */ \ - (a) == '!' || /* secure */ \ - (a) == '+') /* modeless */ - #define IS_IRC_ITEM(rec) (IS_IRC_CHANNEL(rec) || IS_IRC_QUERY(rec)) #define IRC_PROTOCOL (chat_protocol_lookup("IRC")) diff --git a/src/irc/core/modes.c b/src/irc/core/modes.c index a812691c..32a0c169 100644 --- a/src/irc/core/modes.c +++ b/src/irc/core/modes.c @@ -488,7 +488,7 @@ static void event_mode(IRC_SERVER_REC *server, const char *data, params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &mode); - if (!ischannel(*channel)) { + if (!server_ischannel(SERVER(server), channel)) { /* user mode change */ parse_user_mode(server, mode); } else { @@ -536,7 +536,7 @@ static void sig_req_usermode_change(IRC_SERVER_REC *server, const char *data, params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &mode); - if (!ischannel(*target)) { + if (!server_ischannel(SERVER(server), target)) { /* we requested a user mode change, save this */ mode = modes_join(NULL, server->wanted_usermode, mode, FALSE); g_free_not_null(server->wanted_usermode); @@ -856,7 +856,7 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server, target = chanrec->name; irc_send_cmdv(server, "MODE %s", target); - } else if (ischannel(*target)) + } else if (server_ischannel(SERVER(server), target)) channel_set_mode(server, target, mode); else { if (g_ascii_strcasecmp(target, server->nick) == 0) { diff --git a/src/irc/dcc/dcc-autoget.c b/src/irc/dcc/dcc-autoget.c index 38170c56..de23a5d1 100644 --- a/src/irc/dcc/dcc-autoget.c +++ b/src/irc/dcc/dcc-autoget.c @@ -51,7 +51,7 @@ static void sig_dcc_request(GET_DCC_REC *dcc, const char *nickaddr) /* Unless specifically said in dcc_autoget_masks, don't do autogets sent to channels. */ - if (*masks == '\0' && dcc->target != NULL && ischannel(*dcc->target)) + if (*masks == '\0' && dcc->target != NULL && server_ischannel(SERVER(dcc->server), dcc->target)) return; /* don't autoget files beginning with a dot, if download dir is diff --git a/src/irc/flood/flood.c b/src/irc/flood/flood.c index 29502ca6..0944a6eb 100644 --- a/src/irc/flood/flood.c +++ b/src/irc/flood/flood.c @@ -250,7 +250,7 @@ static void flood_privmsg(IRC_SERVER_REC *server, const char *data, params = event_get_params(data, 2, &target, &text); - level = ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS; + level = server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS; if (addr != NULL && !ignore_check(SERVER(server), nick, addr, target, text, level)) flood_newmsg(server, level, nick, addr, target); @@ -287,7 +287,7 @@ static void flood_ctcp(IRC_SERVER_REC *server, const char *data, return; level = g_ascii_strncasecmp(data, "ACTION ", 7) != 0 ? MSGLEVEL_CTCPS : - (ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS); + (server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS); if (!ignore_check(SERVER(server), nick, addr, target, data, level)) flood_newmsg(server, level, nick, addr, target); } diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 4c3bcf68..c334e698 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -262,7 +262,7 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, ignore_next = TRUE; if (*msg != '\001' || msg[strlen(msg)-1] != '\001') { - signal_emit(ischannel(*target) ? + signal_emit(server_ischannel(SERVER(client->server), target) ? "message own_public" : "message own_private", 4, client->server, msg, target, target); } else if (strncmp(msg+1, "ACTION ", 7) == 0) { From fa782ae6bce1efd19f41f3b225e13e390d7629b2 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Fri, 29 May 2015 14:09:55 +0200 Subject: [PATCH 0087/1650] Update sb_search.pl make it easier to bind sb search to a key --- scripts/sb_search.pl | 51 +++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/scripts/sb_search.pl b/scripts/sb_search.pl index 43fc7b55..51b9100b 100644 --- a/scripts/sb_search.pl +++ b/scripts/sb_search.pl @@ -22,7 +22,7 @@ use Irssi; use Irssi::TextUI; use vars qw($VERSION %IRSSI); -$VERSION = '1.0'; +$VERSION = '1.1'; %IRSSI = ( authors => 'Wouter Coekaerts, Emanuele Giaquinta', contact => 'wouter@coekaerts.be, exg@irssi.org', @@ -40,49 +40,66 @@ sub cmd_help { SCROLLBACK SEARCH [-level ] [-regexp] [-case] [-word] [-forward] [-all] [] - -level: only search for lines with the given level. see /help levels - -regexp: the pattern is a regular expression - -case: search case sensitive - -word: pattern must match to full words - -forward: search forwards (default is backwards) - -all: search in all windows - : text to search for + SEARCH: Search for text in the scrollback buffer. + + -regexp: The given text pattern is a regular expression. + -case: Performs a case-sensitive matching. + -word: The text must match full words. + -forward: Search forwards (default is backwards). + -all: Search in all windows. + + Without arguments, the last search is repeated. SCRIPTHELP_EOF ,MSGLEVEL_CLIENTCRAP); } } +my $regex; +my $all; +my $level; -sub cmd_sb_search ($$$) { +sub cmd_sb_search { my ($args, $server, $witem) = @_; ### handle options my ($options, $pattern) = Irssi::command_parse_options('scrollback search', $args); - my $level; + my $forward = defined(delete $options->{forward}); + + if (!%$options && !$pattern) { + return if !$regex && !defined $level; + } else { + $all = defined($options->{all}); + $level = MSGLEVEL_ALL; + undef $regex; + } + if (defined($options->{level})) { $level = $options->{level}; $level =~ y/,/ /; $level = Irssi::combine_level(0, $level); - } else { - return if (!$pattern); - $level = MSGLEVEL_ALL; } - my $regex; if ($pattern) { my $flags = defined($options->{case}) ? '' : '(?i)'; my $b = defined($options->{word}) ? '\b' : ''; if (defined($options->{regexp})) { - $regex = qr/$flags$b$pattern$b/; + local $@; + eval { + $regex = qr/$flags$b$pattern$b/; + }; + if ($@) { + my ($err) = $@ =~ /^(.*)/; + $err =~ s/\sat .* line \d+\.$//; + print CLIENTERROR $err; + return; + } } else { $regex = qr/$flags$b\Q$pattern\E$b/; } } - my $forward = defined($options->{forward}); - my $all = defined($options->{all}); ### determine window(s) to search in From e480b9b16579a0434dba61c58dec362511062cb8 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 31 May 2015 15:30:21 +0200 Subject: [PATCH 0088/1650] Improve ischannel_func (#253) The function now skips all the leading characters that are in the STATUSMSG. If the server didn't send the STATUSMSG option then it's assumed to be "@+" for compatibility with bahamut 2.4 (sic). --- src/irc/core/irc-servers.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index c04c4318..31ba397b 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -72,17 +72,17 @@ static int isnickflag_func(SERVER_REC *server, char flag) static int ischannel_func(SERVER_REC *server, const char *data) { IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server; - char *chantypes; + char *chantypes, *statusmsg; 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 = "@+"; - /* @#channel, @+#channel */ - if (data[0] == '@' && data[1] == '+') - data += 2; - else if (data[0] == '@') - data += 1; + while (strchr(statusmsg, *data) != NULL) + data++; return strchr(chantypes, *data) != NULL; } From a79f150a768b66b04f1edbc6ddf27afe13f2e2c1 Mon Sep 17 00:00:00 2001 From: Geert Hauwaerts Date: Fri, 12 Jun 2015 17:23:49 +0200 Subject: [PATCH 0089/1650] Clarify the help for /LIST (#228) Clarify the help for /LIST (#228) --- docs/help/in/list.in | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/help/in/list.in b/docs/help/in/list.in index 14858337..33f05e8b 100644 --- a/docs/help/in/list.in +++ b/docs/help/in/list.in @@ -7,8 +7,8 @@ -yes: Confirms that you want to receive a large amount of data. - The text a channel must match; if no argument is given, the list of all - channels will be displayed. + If the exact name of a channel is given, the only information about this + channel is requested; otherwise, a list of all channels will be displayed. %9Description:%9 @@ -19,7 +19,16 @@ /LIST /LIST -yes - /LIST -yes *ubuntu* + /LIST #ubuntu + /LIST #*ubuntu*,>1 + +%9Remarks:%9 + + Not all networks support server-side filtering and may provide a network + service instead; on IRCnet, you may use the ALIS service: + + /QUOTE SQUERY ALIS :HELP + /MSG ALIS HELP %9See also:%9 QUOTE, STATS, WHOIS From 4cc6fdaaab5db3d22e195b1d0912dae40348e140 Mon Sep 17 00:00:00 2001 From: Geert Hauwaerts Date: Fri, 12 Jun 2015 17:44:13 +0200 Subject: [PATCH 0090/1650] Add server check in irc_server_connect (#208) Fail instead of crash, if irc_server_connect is called without object. (#208) --- src/irc/core/irc-servers.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index d7122eae..c5e1e318 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -314,6 +314,8 @@ SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn) void irc_server_connect(SERVER_REC *server) { + g_return_if_fail(server != NULL); + if (!server_start_connect(server)) { server_connect_unref(server->connrec); g_free(server); From d222c11f74a5662df59e00e7ae6c8105179a804e Mon Sep 17 00:00:00 2001 From: Geert Hauwaerts Date: Fri, 12 Jun 2015 18:50:55 +0200 Subject: [PATCH 0091/1650] Revert "Bug fix - docdir is ignored during installation." --- docs/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Makefile.am b/docs/Makefile.am index 861a2ca4..5e222564 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,3 +1,5 @@ +docdir = $(datadir)/doc/irssi + man_MANS = \ irssi.1 From a663d2f674f1408fcd54a3d1f8823dffdcc8123f Mon Sep 17 00:00:00 2001 From: Geert Hauwaerts Date: Fri, 12 Jun 2015 19:40:15 +0200 Subject: [PATCH 0092/1650] Updated the bundled scripts to their latest version (#143) Updated the bundled scripts to their latest version (#143) Removed sb_search.pl which is not contributed into the script archive, I will poke coekie about it. --- scripts/autoop.pl | 73 +++++++++++++++++-- scripts/autorejoin.pl | 67 ++++++++++-------- scripts/buf.pl | 17 +++-- scripts/dns.pl | 22 +++--- scripts/kills.pl | 9 +-- scripts/mail.pl | 4 +- scripts/mlock.pl | 2 +- scripts/quitmsg.pl | 4 +- scripts/sb_search.pl | 159 ------------------------------------------ scripts/usercount.pl | 3 +- 10 files changed, 140 insertions(+), 220 deletions(-) delete mode 100644 scripts/sb_search.pl diff --git a/scripts/autoop.pl b/scripts/autoop.pl index f7182999..b72def15 100644 --- a/scripts/autoop.pl +++ b/scripts/autoop.pl @@ -5,13 +5,13 @@ use Irssi; use strict; use vars qw($VERSION %IRSSI); -$VERSION = "1.00"; +$VERSION = "1.10"; %IRSSI = ( - authors => 'Timo Sirainen', + authors => 'Timo Sirainen & Jostein Kjønigsen', name => 'autoop', description => 'Simple auto-op script', license => 'Public Domain', - changed => 'Sun Mar 10 23:18 EET 2002' + changed => 'Fri Nov 24 12:55 GMT+1 2014' ); my (%opnicks, %temp_opped); @@ -64,7 +64,7 @@ sub autoop { if (!$temp_opped{$nick} && $server->masks_match($masks, $nick, $host)) { - $channel->command("op $nick"); + $channel->command("/op $nick"); $temp_opped{$nick} = 1; } } @@ -89,3 +89,68 @@ sub event_massjoin { Irssi::command_bind('autoop', 'cmd_autoop'); Irssi::signal_add_last('massjoin', 'event_massjoin'); + +sub load_autoops { + my($file) = Irssi::get_irssi_dir."/autoop"; + my($count) = 0; + local(*CONF); + + %opnicks = (); + open(CONF, "<", "$file") or return; + while (my $line = ) { + if ($line !=~ /^\s*$/) { + cmd_autoop($line); + $count++; + } + } + close(CONF); + + Irssi::print("Loaded $count channels from $file"); +} + +# --------[ save_autoops ]------------------------------------------------ + +sub save_autoops { + my($auto) = @_; + my($file) = Irssi::get_irssi_dir."/autoop"; + my($count) = 0; + my($channel) = ""; + local(*CONF); + + return if $auto; + + open(CONF, ">", "$file"); + foreach $channel (keys %opnicks) { + my $masks = $opnicks{$channel}; + print CONF "$channel\t$masks\n"; + $count++; + } + close(CONF); + + Irssi::print("Saved $count channels to $file") + unless $auto; +} + + +# --------[ sig_setup_reread ]------------------------------------------ + +# main setup is reread, so let us do it too +sub sig_setup_reread { + load_autoops; +} + +# --------[ sig_setup_save ]-------------------------------------------- + +# main config is saved, and so we should save too +sub sig_setup_save { + my($mainconf,$auto) = @_; + save_autoops($auto); +} + +# persistance + +Irssi::signal_add('setup saved', 'sig_setup_save'); +Irssi::signal_add('setup reread', 'sig_setup_reread'); + +# ensure we load persisted values on start +load_autoops; diff --git a/scripts/autorejoin.pl b/scripts/autorejoin.pl index 2d23449f..42c97da7 100644 --- a/scripts/autorejoin.pl +++ b/scripts/autorejoin.pl @@ -1,6 +1,5 @@ -# automatically rejoin to channel after kicked - -# /SET autorejoin_channels #channel1 #channel2 ... +# automatically rejoin to channel after kick +# delayed rejoin: Lam 28.10.2001 (lam@lac.pl) # NOTE: I personally don't like this feature, in most channels I'm in it # will just result as ban. You've probably misunderstood the idea of /KICK @@ -10,43 +9,49 @@ use Irssi; use Irssi::Irc; use strict; use vars qw($VERSION %IRSSI); - -$VERSION = "1.00"; +$VERSION = "1.0.0"; %IRSSI = ( - authors => 'Timo Sirainen', - name => 'autorejoin', - description => 'Automatically rejoin to channel after kicked', - license => 'Public Domain', - changed => 'Sun Mar 10 23:18 EET 2002' + authors => "Timo 'cras' Sirainen, Leszek Matok", + contact => "lam\@lac.pl", + name => "autorejoin", + description => "Automatically rejoin to channel after being kick, after a (short) user-defined delay", + license => "GPLv2", + changed => "10.3.2002 14:00" ); -sub channel_rejoin { - my ($server, $channel) = @_; - # check if channel has password - my $chanrec = $server->channel_find($channel); - my $password = $chanrec->{key} if ($chanrec); +# How many seconds to wait before the rejoin? +# TODO: make this a /setting +my $delay = 5; - # We have to use send_raw() because the channel record still - # exists and irssi won't even try to join to it with command() - $server->send_raw("JOIN $channel $password"); +my @tags; +my $acttag = 0; + +sub rejoin { + my ( $data ) = @_; + my ( $tag, $servtag, $channel, $pass ) = split( / +/, $data ); + + my $server = Irssi::server_find_tag( $servtag ); + $server->send_raw( "JOIN $channel $pass" ) if ( $server ); + Irssi::timeout_remove( $tags[$tag] ); } sub event_rejoin_kick { - my ($server, $data) = @_; - my ($channel, $nick) = split(/ +/, $data); + my ( $server, $data ) = @_; + my ( $channel, $nick ) = split( / +/, $data ); - return if ($server->{nick} ne $nick); + return if ( $server->{ nick } ne $nick ); - # check if we want to autorejoin this channel - my @chans = split(/[ ,]+/, Irssi::settings_get_str('autorejoin_channels')); - foreach my $chan (@chans) { - if (lc($chan) eq lc($channel)) { - channel_rejoin($server, $channel); - last; - } - } + # check if channel has password + my $chanrec = $server->channel_find( $channel ); + my $password = $chanrec->{ key } if ( $chanrec ); + my $rejoinchan = $chanrec->{ name } if ( $chanrec ); + my $servtag = $server->{ tag }; + + Irssi::print "Rejoining $rejoinchan in $delay seconds."; + $tags[$acttag] = Irssi::timeout_add( $delay * 1000, "rejoin", "$acttag $servtag $rejoinchan $password" ); + $acttag++; + $acttag = 0 if ( $acttag > 60 ); } -Irssi::settings_add_str('misc', 'autorejoin_channels', ''); -Irssi::signal_add('event kick', 'event_rejoin_kick'); +Irssi::signal_add( 'event kick', 'event_rejoin_kick' ); diff --git a/scripts/buf.pl b/scripts/buf.pl index 43b4b3dd..da50e821 100644 --- a/scripts/buf.pl +++ b/scripts/buf.pl @@ -40,7 +40,7 @@ use Data::Dumper; my %suppress; sub upgrade { - open BUF, sprintf('>%s/scrollbuffer', get_irssi_dir) or die $!; + open BUF, q{>}, sprintf('%s/scrollbuffer', get_irssi_dir) or die $!; print BUF join("\0", map $_->{server}->{address} . $_->{name}, channels), "\n"; for my $window (windows) { next unless defined $window; @@ -66,7 +66,7 @@ sub upgrade { } sub restore { - open BUF, sprintf('<%s/scrollbuffer', get_irssi_dir) or die $!; + open BUF, q{<}, sprintf('%s/scrollbuffer', get_irssi_dir) or die $!; my @suppress = split /\0/, ; if (settings_get_bool 'upgrade_suppress_join') { chomp $suppress[-1]; @@ -98,14 +98,13 @@ sub restore { sub suppress { my ($first, $second) = @_; - return - unless scalar keys %suppress - and settings_get_bool 'upgrade_suppress_join'; - my $key = $first->{address} . - (grep { (s/^://, /^[#!+&]/) } split ' ', $second)[0]; + return unless scalar keys %suppress and settings_get_bool 'upgrade_suppress_join'; + my $key_part = (grep { /^:?[#!+&]/ } split ' ', $second)[0]; + $key_part =~ s/^://; + my $key = $first->{address} . $key_part; if (exists $suppress{$key} and $suppress{$key}--) { - signal_stop(); - delete $suppress{$key} unless $suppress{$key}; + signal_stop(); + delete $suppress{$key} unless $suppress{$key}; } } diff --git a/scripts/dns.pl b/scripts/dns.pl index 612fab0e..989cdc3e 100644 --- a/scripts/dns.pl +++ b/scripts/dns.pl @@ -1,18 +1,24 @@ # /DNS || ... +# version 2.1.1 +# +# updated the script to fix a bug where the script would let +# a trailing whitespace go through (ex: tab completion) +# - inch -use Irssi; use strict; use Socket; use POSIX; use vars qw($VERSION %IRSSI); -$VERSION = "2.1"; +$VERSION = "2.1.1"; %IRSSI = ( - authors => 'Timo Sirainen', - name => 'dns', - description => '/DNS || ...', - license => 'Public Domain', - changed => 'Sun Mar 10 23:23 EET 2002' + authors => "Timo \'cras\' Sirainen", + contact => "tss\@iki.fi", + name => "dns", + description => "/DNS || ...", + license => "Public Domain", + url => "http://irssi.org/", + changed => "2002-03-04T22:47+0100" ); my (%resolve_hosts, %resolve_nicks, %resolve_print); # resolve queues @@ -28,7 +34,7 @@ my $pipe_tag; sub cmd_dns { my ($nicks, $server) = @_; return if !$nicks; - + $nicks =~ s/\s+$//; # get list of nicks/hosts we want to know my $tag = !$server ? undef : $server->{tag}; my $ask_nicks = ""; diff --git a/scripts/kills.pl b/scripts/kills.pl index 7ed2d533..50d9383d 100644 --- a/scripts/kills.pl +++ b/scripts/kills.pl @@ -10,6 +10,7 @@ # There's a pretty good explanation of (ircnet) ircd's server kills in # http://www.irc.org/tech_docs/ircnet/kills.html +use strict; use Irssi; use vars qw($VERSION %IRSSI); @@ -47,13 +48,13 @@ sub msg_quit { my @printargs = (); if ($killmsg =~ /([^ ]*) != (.*)/) { # 1 != 2 - my $server1 = $1, $server2 = $2; + my $server1 = $1, my $server2 = $2; $server1 =~ s/([^\[]*)\[([^\]]*)\]/\1/; $msg .= "$2 != $server2"; } elsif ($killmsg =~ /([^ ]*) <- (.*)/) { # 1 <- 2 - my $server1 = $1, $server2 = $2; + my $server1 = $1, my $server2 = $2; if ($server1 =~ /^\(/) { # (addr1)server1 <- (add2)server2 @@ -84,9 +85,9 @@ sub msg_quit { $msg = $killmsg; } - @list = $server->nicks_get_same($nick); + my @list = $server->nicks_get_same($nick); while (@list) { - $channel = $list[0]; + my $channel = $list[0]; shift @list; # skip nick record shift @list; diff --git a/scripts/mail.pl b/scripts/mail.pl index 33b3c22e..190c33af 100644 --- a/scripts/mail.pl +++ b/scripts/mail.pl @@ -1,3 +1,5 @@ +use strict; +use vars qw($VERSION %IRSSI); $VERSION = "2.92"; %IRSSI = ( authors => "Timo Sirainen, Matti Hiljanen, Joost Vunderink, Bart Matthaei", @@ -114,7 +116,7 @@ sub mbox_count { $last_mtime = $mtime; my $f = gensym; - return 0 if (!open($f, $mailfile)); + return 0 if (!open($f, "<", $mailfile)); # count new mails only my $internal_removed = 0; diff --git a/scripts/mlock.pl b/scripts/mlock.pl index ed2fe52b..bf2fd002 100644 --- a/scripts/mlock.pl +++ b/scripts/mlock.pl @@ -113,7 +113,7 @@ sub mlock_check_mode { } if ($modecmd ne "") { - $channel->{server}->command("mode $channame $modecmd$extracmd"); + $channel->{server}->command("/mode $channame $modecmd$extracmd"); } } diff --git a/scripts/quitmsg.pl b/scripts/quitmsg.pl index 41bddaa8..e289468c 100644 --- a/scripts/quitmsg.pl +++ b/scripts/quitmsg.pl @@ -21,7 +21,7 @@ sub cmd_quit { my ($data, $server, $channel) = @_; return if ($data ne ""); - open (f, $quitfile) || return; + open (f, "<", $quitfile) || return; my $lines = 0; while() { $lines++; }; my $line = int(rand($lines))+1; @@ -38,7 +38,7 @@ sub cmd_quit { close(f); foreach my $server (Irssi::servers) { - $server->command("disconnect ".$server->{tag}." $quitmsg"); + $server->command("/disconnect ".$server->{tag}." $quitmsg"); } } diff --git a/scripts/sb_search.pl b/scripts/sb_search.pl deleted file mode 100644 index 51b9100b..00000000 --- a/scripts/sb_search.pl +++ /dev/null @@ -1,159 +0,0 @@ -# sb_search.pl - search in your scrollback, scroll to a match -# Do /HELP SCROLLBACK for help - -# Copyright (C) 2008 Wouter Coekaerts , Emanuele Giaquinta -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -use strict; -use Irssi; -use Irssi::TextUI; -use vars qw($VERSION %IRSSI); - -$VERSION = '1.1'; -%IRSSI = ( - authors => 'Wouter Coekaerts, Emanuele Giaquinta', - contact => 'wouter@coekaerts.be, exg@irssi.org', - name => 'sb_search', - description => 'search in your scrollback, scroll to a match', - license => 'GPLv2 or later', - url => 'http://wouter.coekaerts.be/irssi/', - changed => '$LastChangedDate$', -); - -sub cmd_help { - my ($args, $server, $witem) = @_; - if ($args =~ /^scrollback( search)? *$/i) { - Irssi::print ( <] [-regexp] [-case] [-word] [-forward] [-all] [] - - SEARCH: Search for text in the scrollback buffer. - - -regexp: The given text pattern is a regular expression. - -case: Performs a case-sensitive matching. - -word: The text must match full words. - -forward: Search forwards (default is backwards). - -all: Search in all windows. - - Without arguments, the last search is repeated. -SCRIPTHELP_EOF - ,MSGLEVEL_CLIENTCRAP); - } -} - -my $regex; -my $all; -my $level; - -sub cmd_sb_search { - my ($args, $server, $witem) = @_; - - ### handle options - - my ($options, $pattern) = Irssi::command_parse_options('scrollback search', $args); - - my $forward = defined(delete $options->{forward}); - - if (!%$options && !$pattern) { - return if !$regex && !defined $level; - } else { - $all = defined($options->{all}); - $level = MSGLEVEL_ALL; - undef $regex; - } - - if (defined($options->{level})) { - $level = $options->{level}; - $level =~ y/,/ /; - $level = Irssi::combine_level(0, $level); - } - - if ($pattern) { - my $flags = defined($options->{case}) ? '' : '(?i)'; - my $b = defined($options->{word}) ? '\b' : ''; - if (defined($options->{regexp})) { - local $@; - eval { - $regex = qr/$flags$b$pattern$b/; - }; - if ($@) { - my ($err) = $@ =~ /^(.*)/; - $err =~ s/\sat .* line \d+\.$//; - print CLIENTERROR $err; - return; - } - } else { - $regex = qr/$flags$b\Q$pattern\E$b/; - } - } - - - ### determine window(s) to search in - - my $current_win = ref $witem ? $witem->window() : Irssi::active_win(); - - my @windows; - if ($all) { - # cycle backward or forwards over all windows starting from current - # for example, searching backward through 5 windows, with window 3 active: search order is 3,2,1,5,4 - # if we're searching forward: 3,4,5,1,2 - my $order = $forward ? 1 : -1; - @windows = sort {$order * ($a->{refnum} cmp $b->{refnum})} Irssi::windows(); - my @before_windows = grep {($_->{refnum} cmp $current_win->{refnum}) == $order} @windows; - my @after_windows = grep {($_->{refnum} cmp $current_win->{refnum}) == -$order} @windows; - @windows = ($current_win, @before_windows, @after_windows); - } else { - @windows = ($current_win); - } - - ### do the search - - foreach my $win (@windows) { - my $view = $win->view; - - ## determine line to start from - my $line; - if ($all && $win != $current_win) { - if ($forward) { # first line - $line = $view->get_lines; - } else { # last line - $line = $view->{startline}; - while ($line->next) { - $line = $line->next - } - } - } else { # line after or before first visible line - $line = $forward ? $view->{startline}->next : $view->{startline}->prev; - } - - ## loop over the lines - while (defined $line) { - my $line_level = $line->{info}{level}; - if ($line_level & $level && $line->get_text(0) =~ $regex) { - $view->scroll_line($line); - if ($all) { - Irssi::command('window goto ' . $win->{refnum}); - } - return; - } - $line = $forward ? $line->next : $line->prev; - } - } -} - -Irssi::command_bind('scrollback search', \&cmd_sb_search); -Irssi::command_bind_last('help', \&cmd_help); -Irssi::command_set_options('scrollback search', '-level regexp case word forward all'); diff --git a/scripts/usercount.pl b/scripts/usercount.pl index 46dc0b46..613da1de 100644 --- a/scripts/usercount.pl +++ b/scripts/usercount.pl @@ -1,4 +1,6 @@ +use strict; use Irssi 20040119.2359 (); +use vars qw($VERSION %IRSSI); $VERSION = "1.19"; %IRSSI = ( authors => 'David Leadbeater, Timo Sirainen, Georg Lukas', @@ -29,7 +31,6 @@ $VERSION = "1.19"; # sb_uc_space = " "; -use strict; use Irssi::TextUI; my ($ircops, $ops, $halfops, $voices, $normal, $total); From e2eb2483b7d642e8dee31735f70cfb963d16323c Mon Sep 17 00:00:00 2001 From: Geert Hauwaerts Date: Fri, 12 Jun 2015 20:41:47 +0200 Subject: [PATCH 0093/1650] Updated the man page (#251) Updated the man page (#251) --- docs/irssi.1 | 64 +++++++++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 41 deletions(-) diff --git a/docs/irssi.1 b/docs/irssi.1 index e86be7ca..f38b639e 100644 --- a/docs/irssi.1 +++ b/docs/irssi.1 @@ -1,12 +1,13 @@ -.TH Irssi 1 "September 2002" "Irssi IRC client" +.TH Irssi 1 "June 2015" "Irssi IRC client" .SH NAME Irssi \- a modular IRC client for UNIX .SH SYNOPSIS .B irssi -[-dv!?] [-c server] [-p port] [-n nickname] [-w password] [-h hostname] +[--config=PATH] [--home=PATH] [-dv!?] [-c server] [-p port] [-n nickname] +[-w password] [-h hostname] .SH DESCRIPTION .B Irssi -is a modular Internet Relay Chat client. It is highly extensible and +is a modular Internet Relay Chat client; it is highly extensible and very secure. Being a fullscreen, termcap based client with many features, .B Irssi @@ -16,16 +17,15 @@ is easily extensible through scripts and modules. .BI "\-\-config="FILE use .I FILE -instead of ~/.irssi/config. +instead of ~/.irssi/config .TP .BI "\-\-home="PATH .I PATH -specifies the home directory of Irssi. -Default is +specifies the home directory of Irssi; default is .BR ~/.irssi .TP .BI "\-c, \-\-connect="SERVER -connects to +connect to .I SERVER .TP .BI "\-w, \-\-password="PASSWORD @@ -39,71 +39,53 @@ automatically connect to on server. .TP .BI "\-!, \-\-noconnect" -disables autoconnecting. +disable autoconnecting of servers .TP .BI "\-n, \-\-nick="NICKNAME specify .I NICKNAME -as your nick. +as your nick .TP .BI "\-h, \-\-hostname="HOSTNAME use .I HOSTNAME -for your irc session. +for your irc session .TP .BI "\-d, \-\-dummy" -use dummy terminal mode. +use dummy terminal mode .TP .BI "\-v, \-\-version" -display the version of Irssi. +display the version of Irssi .TP .BI "\-?, \-\-help" -show a help message. +show a help message .SH SEE ALSO .B Irssi -has been supplied with a huge amount of documentation. Check /help or look -at the files contained by /usr/share/doc/irssi* +has a solid amount of documentation available; check /HELP or look online +at http://www.irssi.org .SH FILES .TP -.I /etc/irssi.conf -Global configuration file -.TP .I ~/.irssi/config -Personal configuration file +personal configuration file .TP .I ~/.irssi/config.autosave -Automatic save of the personal config file when it was changed externally +automatic save of the personal config file when it was changed externally .TP .I ~/.irssi/default.theme -Default irssi theme +default irssi theme .TP .I ~/.irssi/away.log -Logged messages in away status -.TP -.I /usr/share/irssi/help/ -Directory including many help files -.TP -.I /usr/share/irssi/scripts/ -Global scripts directory -.TP -.I /usr/share/irssi/themes/ -Global themes directory +logged messages in away status .TP .I ~/.irssi/scripts/ -Default scripts directory +default scripts directory .TP .I ~/.irssi/scripts/autorun/ -Directory containing links to scripts that should be loaded +directory containing links to scripts that should be loaded automatically on startup .TP .I ~/.irssi/startup -File containing a list of commands to execute on startup +file containing a list of commands to execute on startup .SH AUTHORS/CREDITS .B Irssi -was written by Timo Sirainen -.B -.sp -This manpage was written by Istvan Sebestyen -.BR -and Stefan Tomanek -.BR +was written by Timo Sirainen; this manpage was written by Istvan Sebestyen, Stefan Tomanek, Geert Hauwaerts. From b90402b7fcc1d2d0b1d07fee973af3aa75c50bfa Mon Sep 17 00:00:00 2001 From: Geert Hauwaerts Date: Fri, 12 Jun 2015 20:44:32 +0200 Subject: [PATCH 0094/1650] Proper removal of sb_search.pl (#143) Proper removal of sb_search.pl (#143) --- scripts/Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 23eb7198..cd795153 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -11,7 +11,6 @@ script_DATA = \ mail.pl \ mlock.pl \ quitmsg.pl \ - sb_search.pl \ scriptassist.pl \ usercount.pl From 6fcafc599350737d0d14f3c863af594efc391124 Mon Sep 17 00:00:00 2001 From: Geert Hauwaerts Date: Fri, 12 Jun 2015 21:13:27 +0200 Subject: [PATCH 0095/1650] 1k+ windows are now the default formatting (#223) 1k+ windows are now the default formatting (#223) --- src/fe-common/core/module-formats.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index db11fae1..4ae26950 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -42,8 +42,8 @@ FORMAT_REC fecommon_core_formats[] = { { "window_set_immortal", "Window is now immortal", 0 }, { "window_unset_immortal", "Window isn't immortal anymore", 0 }, { "window_immortal_error", "Window is immortal, if you really want to close it, say /WINDOW IMMORTAL OFF", 0 }, - { "windowlist_header", "%#Ref Name Active item Server Level", 0 }, - { "windowlist_line", "%#$[3]0 %|$[20]1 $[15]2 $[15]3 $4", 5, { 1, 0, 0, 0, 0 } }, + { "windowlist_header", "%#Ref Name Active item Server Level", 0 }, + { "windowlist_line", "%#$[4]0 %|$[20]1 $[15]2 $[15]3 $4", 5, { 1, 0, 0, 0, 0 } }, { "windowlist_footer", "", 0 }, { "windows_layout_saved", "Layout of windows is now remembered", 0 }, { "windows_layout_reset", "Layout of windows reset to defaults", 0 }, From a47f45b5b7438209177d76f3efde559e61e5bdb7 Mon Sep 17 00:00:00 2001 From: dequis Date: Sun, 14 Jun 2015 11:57:11 -0300 Subject: [PATCH 0096/1650] Rename /proxy command to /irssiproxy for clarity --- docs/help/in/irssiproxy.in | 14 ++++++++++++++ docs/help/in/proxy.in | 14 -------------- docs/proxy.txt | 2 +- src/irc/proxy/proxy.c | 16 ++++++++-------- 4 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 docs/help/in/irssiproxy.in delete mode 100644 docs/help/in/proxy.in diff --git a/docs/help/in/irssiproxy.in b/docs/help/in/irssiproxy.in new file mode 100644 index 00000000..79d75b91 --- /dev/null +++ b/docs/help/in/irssiproxy.in @@ -0,0 +1,14 @@ + +@SYNTAX:irssiproxy@ + +%9Description:%9 + + Displays the list of clients connected to irssiproxy. + +%9Examples:%9 + + /IRSSIPROXY + /IRSSIPROXY STATUS + +%9See also:%9 LOAD PROXY, SET irssiproxy + diff --git a/docs/help/in/proxy.in b/docs/help/in/proxy.in deleted file mode 100644 index 2dc61f43..00000000 --- a/docs/help/in/proxy.in +++ /dev/null @@ -1,14 +0,0 @@ - -@SYNTAX:proxy@ - -%9Description:%9 - - Displays the list of clients connected to the proxy. - -%9Examples:%9 - - /PROXY - /PROXY STATUS - -%9See also:%9 LOAD PROXY, SET irssiproxy - diff --git a/docs/proxy.txt b/docs/proxy.txt index 759ef1dc..e6360a82 100644 --- a/docs/proxy.txt +++ b/docs/proxy.txt @@ -45,4 +45,4 @@ Once everything is set up, you can enable / disable the proxy: When the proxy is configured and running, the following command will show all the currently connected clients: - /PROXY status + /IRSSIPROXY status diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c index 65c778d1..ce79e2b7 100644 --- a/src/irc/proxy/proxy.c +++ b/src/irc/proxy/proxy.c @@ -25,8 +25,8 @@ #include "fe-common/core/printtext.h" -/* SYNTAX: PROXY STATUS */ -static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server) +/* SYNTAX: IRSSIPROXY STATUS */ +static void cmd_irssiproxy_status(const char *data, IRC_SERVER_REC *server) { if (!settings_get_bool("irssiproxy")) { printtext(server, NULL, MSGLEVEL_CLIENTNOTICE, @@ -51,15 +51,15 @@ static void cmd_proxy_status(const char *data, IRC_SERVER_REC *server) } } -/* SYNTAX: PROXY */ -static void cmd_proxy(const char *data, IRC_SERVER_REC *server, void *item) +/* SYNTAX: IRSSIPROXY */ +static void cmd_irssiproxy(const char *data, IRC_SERVER_REC *server, void *item) { if (*data == '\0') { - cmd_proxy_status(data, server); + cmd_irssiproxy_status(data, server); return; } - command_runsub("proxy", data, server, item); + command_runsub("irssiproxy", data, server, item); } static void irc_proxy_setup_changed(void) @@ -92,8 +92,8 @@ void irc_proxy_init(void) "... to set them."); } - command_bind("proxy", NULL, (SIGNAL_FUNC) cmd_proxy); - command_bind("proxy status", NULL, (SIGNAL_FUNC) cmd_proxy_status); + command_bind("irssiproxy", NULL, (SIGNAL_FUNC) cmd_irssiproxy); + command_bind("irssiproxy status", NULL, (SIGNAL_FUNC) cmd_irssiproxy_status); signal_add_first("setup changed", (SIGNAL_FUNC) irc_proxy_setup_changed); From 51496cd09f5d2f2da0a4ae678663c66e2ceae17c Mon Sep 17 00:00:00 2001 From: dequis Date: Sun, 14 Jun 2015 16:41:52 -0300 Subject: [PATCH 0097/1650] Fix 'address already in use' when changing irssiproxy_ports When changing the value of irssiproxy_ports to use a different network name in a port that was already bound (so like changing from asd=6667 to sdf=6667) it would throw "address already in use". This fixes it by delaying the add_listen() calls after all the remove_listen() were called. --- src/irc/proxy/listen.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index a560801d..dc354c30 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -642,7 +642,8 @@ static void remove_listen(LISTEN_REC *rec) static void read_settings(void) { LISTEN_REC *rec; - GSList *remove_listens; + GSList *remove_listens = NULL; + GSList *add_listens = NULL; char **ports, **tmp, *ircnet, *port; int portnum; @@ -661,17 +662,30 @@ static void read_settings(void) continue; rec = find_listen(ircnet, portnum); - if (rec == NULL) - add_listen(ircnet, portnum); - else + if (rec == NULL) { + rec = g_new0(LISTEN_REC, 1); + rec->ircnet = ircnet; /* borrow */ + rec->port = portnum; + add_listens = g_slist_prepend(add_listens, rec); + } else { + /* remove from the list of listens to remove == keep it */ remove_listens = g_slist_remove(remove_listens, rec); + } } - g_strfreev(ports); while (remove_listens != NULL) { - remove_listen(remove_listens->data); + remove_listen(remove_listens->data); remove_listens = g_slist_remove(remove_listens, remove_listens->data); } + + while (add_listens != NULL) { + rec = add_listens->data; + add_listen(rec->ircnet, rec->port); + g_free(rec); + add_listens = g_slist_remove(add_listens, add_listens->data); + } + + g_strfreev(ports); } static void sig_dump(CLIENT_REC *client, const char *data) From a393c675400a41f7cc3df988c25242857da678a4 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Thu, 9 Jul 2015 14:20:30 +0200 Subject: [PATCH 0098/1650] Introduce check for git commands in autogen This avoids a misleading compile error when users try to `make` an incomplete (or non-git) check-out. --- autogen.sh | 4 ++++ irssi-version.sh | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/autogen.sh b/autogen.sh index 466a5a05..dd556216 100755 --- a/autogen.sh +++ b/autogen.sh @@ -18,6 +18,10 @@ perl syntax.pl echo "Creating ChangeLog..." git log > $srcdir/ChangeLog +if test "$?" -ne 0; then + echo "**Error**: ${PKG_NAME} Autogen must be run in a git clone, cannot proceed." + exit 1 +fi files=`echo docs/help/in/*.in|sed -e 's,docs/help/in/Makefile.in ,,' -e 's,docs/help/in/,!,g' -e 's/\.in /.in ?/g'` cat docs/help/in/Makefile.am.gen|sed "s/@HELPFILES@/$files/g"|sed 's/?/\\?/g'|tr '!?' '\t\n' > docs/help/in/Makefile.am diff --git a/irssi-version.sh b/irssi-version.sh index 7588182d..1e9eae34 100755 --- a/irssi-version.sh +++ b/irssi-version.sh @@ -5,6 +5,12 @@ DATE=`GIT_DIR=$1/.git git log -1 --pretty=format:%ai HEAD` VERSION_DATE=`echo $DATE | cut -f 1 -d ' ' | tr -d -` VERSION_TIME=`echo $DATE | cut -f 2 -d ' ' | awk -F: '{printf "%d", $1$2}'` +if test -z "$VERSION_DATE"; then + exec>&2 + echo "**Error**: `basename "$0"` must be run in a git clone, cannot proceed." + exit 1 +fi + echo "#define IRSSI_VERSION_DATE $VERSION_DATE" echo "#define IRSSI_VERSION_TIME $VERSION_TIME" From 8e71d6ec739ec74fbb5c712e9341d4319a17d8f5 Mon Sep 17 00:00:00 2001 From: kyak Date: Sun, 19 Jul 2015 09:45:50 +0300 Subject: [PATCH 0099/1650] Add expandos for hostname See http://bugs.irssi.org/index.php?do=details&task_id=829 --- src/irc/core/irc-expandos.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c index 5d2de503..cc46ece5 100644 --- a/src/irc/core/irc-expandos.c +++ b/src/irc/core/irc-expandos.c @@ -76,6 +76,29 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret) return g_strconcat(username, "@", hostname, NULL);; } +/* your hostname address (host) */ +static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret) +{ + IRC_SERVER_REC *ircserver; + char hostname[100]; + char **list; + + ircserver = IRC_SERVER(server); + + /* prefer the _real_ /userhost reply */ + if (ircserver != NULL && ircserver->userhost != NULL) { + list = g_strsplit(ircserver->userhost, "@", -1); + return list[1]; + } + + /* haven't received userhost reply yet. guess something */ + *free_ret = TRUE; + + if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0') + strcpy(hostname, "??"); + return g_strconcat(hostname, NULL); +} + /* user mode in active server */ static char *expando_usermode(SERVER_REC *server, void *item, int *free_ret) { @@ -136,6 +159,9 @@ void irc_expandos_init(void) expando_create("X", expando_userhost, "window changed", EXPANDO_ARG_NONE, "window server changed", EXPANDO_ARG_WINDOW, NULL); + expando_create("x", expando_hostname, + "window changed", EXPANDO_ARG_NONE, + "window server changed", EXPANDO_ARG_WINDOW, NULL); expando_create("usermode", expando_usermode, "window changed", EXPANDO_ARG_NONE, "window server changed", EXPANDO_ARG_WINDOW, @@ -164,6 +190,7 @@ void irc_expandos_deinit(void) expando_destroy("H", expando_server_numeric); expando_destroy("S", expando_servername); expando_destroy("X", expando_userhost); + expando_destroy("x", expando_hostname); expando_destroy("usermode", expando_usermode); expando_destroy("cumode", expando_cumode); From 92d03fe11ed2e4837d0137893fafd758ff0434d5 Mon Sep 17 00:00:00 2001 From: blha303 Date: Sat, 25 Jul 2015 02:41:26 -0400 Subject: [PATCH 0100/1650] Replace \n with \r\n in irssiproxy source, fixes bug --- src/irc/proxy/dump.c | 38 +++++++++++++++++++------------------- src/irc/proxy/listen.c | 16 ++++++++-------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/irc/proxy/dump.c b/src/irc/proxy/dump.c index 3d7bf546..455a2fe3 100644 --- a/src/irc/proxy/dump.c +++ b/src/irc/proxy/dump.c @@ -83,7 +83,7 @@ void proxy_outserver(CLIENT_REC *client, const char *data, ...) va_start(args, data); str = g_strdup_vprintf(data, args); - proxy_outdata(client, ":%s!%s@proxy %s\n", client->nick, + proxy_outdata(client, ":%s!%s@proxy %s\r\n", client->nick, settings_get_str("user_name"), str); g_free(str); @@ -106,7 +106,7 @@ void proxy_outserver_all(IRC_SERVER_REC *server, const char *data, ...) CLIENT_REC *rec = tmp->data; if (rec->connected && rec->server == server) { - proxy_outdata(rec, ":%s!%s@proxy %s\n", rec->nick, + proxy_outdata(rec, ":%s!%s@proxy %s\r\n", rec->nick, settings_get_str("user_name"), str); } } @@ -132,7 +132,7 @@ void proxy_outserver_all_except(CLIENT_REC *client, const char *data, ...) if (rec->connected && rec != client && rec->server == client->server) { - proxy_outdata(rec, ":%s!%s@proxy %s\n", rec->nick, + proxy_outdata(rec, ":%s!%s@proxy %s\r\n", rec->nick, settings_get_str("user_name"), str); } } @@ -169,7 +169,7 @@ static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client) NICK_REC *nick = tmp->data; if (str->len >= 500) { - g_string_append_c(str, '\n'); + g_string_append_c(str, '\r\n'); proxy_outdata(client, "%s", str->str); create_names_start(str, channel, client); first = TRUE; @@ -186,21 +186,21 @@ static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client) } g_slist_free(nicks); - g_string_append_c(str, '\n'); + g_string_append_c(str, '\r\n'); proxy_outdata(client, "%s", str->str); g_string_free(str, TRUE); - proxy_outdata(client, ":%s 366 %s %s :End of /NAMES list.\n", + proxy_outdata(client, ":%s 366 %s %s :End of /NAMES list.\r\n", client->proxy_address, client->nick, channel->name); if (channel->topic != NULL) { /* this is needed because the topic may be encoded into other charsets internaly */ recoded = recode_out(SERVER(client->server), channel->topic, channel->name); - proxy_outdata(client, ":%s 332 %s %s :%s\n", + proxy_outdata(client, ":%s 332 %s %s :%s\r\n", client->proxy_address, client->nick, channel->name, recoded); g_free(recoded); if (channel->topic_time > 0) - proxy_outdata(client, ":%s 333 %s %s %s %d\n", + proxy_outdata(client, ":%s 333 %s %s %s %d\r\n", client->proxy_address, client->nick, channel->name, channel->topic_by, channel->topic_time); } @@ -212,7 +212,7 @@ void proxy_client_reset_nick(CLIENT_REC *client) g_strcmp0(client->nick, client->server->nick) == 0) return; - proxy_outdata(client, ":%s!proxy NICK :%s\n", + proxy_outdata(client, ":%s!proxy NICK :%s\r\n", client->nick, client->server->nick); g_free(client->nick); @@ -236,13 +236,13 @@ void proxy_dump_data(CLIENT_REC *client) proxy_client_reset_nick(client); /* welcome info */ - proxy_outdata(client, ":%s 001 %s :Welcome to the Internet Relay Network %s!%s@proxy\n", client->proxy_address, client->nick, client->nick, settings_get_str("user_name")); - proxy_outdata(client, ":%s 002 %s :Your host is irssi-proxy, running version %s\n", client->proxy_address, client->nick, PACKAGE_VERSION); - proxy_outdata(client, ":%s 003 %s :This server was created ...\n", client->proxy_address, client->nick); + proxy_outdata(client, ":%s 001 %s :Welcome to the Internet Relay Network %s!%s@proxy\r\n", client->proxy_address, client->nick, client->nick, settings_get_str("user_name")); + proxy_outdata(client, ":%s 002 %s :Your host is irssi-proxy, running version %s\r\n", client->proxy_address, client->nick, PACKAGE_VERSION); + proxy_outdata(client, ":%s 003 %s :This server was created ...\r\n", client->proxy_address, client->nick); if (client->server == NULL || !client->server->emode_known) - proxy_outdata(client, ":%s 004 %s %s %s oirw abiklmnopqstv\n", client->proxy_address, client->nick, client->proxy_address, PACKAGE_VERSION); + proxy_outdata(client, ":%s 004 %s %s %s oirw abiklmnopqstv\r\n", client->proxy_address, client->nick, client->proxy_address, PACKAGE_VERSION); else - proxy_outdata(client, ":%s 004 %s %s %s oirw abeIiklmnopqstv\n", client->proxy_address, client->nick, client->proxy_address, PACKAGE_VERSION); + proxy_outdata(client, ":%s 004 %s %s %s oirw abeIiklmnopqstv\r\n", client->proxy_address, client->nick, client->proxy_address, PACKAGE_VERSION); if (client->server != NULL && client->server->isupport_sent) { isupport_out = g_string_new(NULL); @@ -267,7 +267,7 @@ void proxy_dump_data(CLIENT_REC *client) count = 0; if (paramstr->len > 0) g_string_truncate(paramstr, paramstr->len-1); - g_string_append_printf(paramstr, " :are supported by this server\n"); + g_string_append_printf(paramstr, " :are supported by this server\r\n"); proxy_outdata(client, "%s", paramstr->str); g_string_truncate(paramstr, 0); g_string_printf(paramstr, ":%s 005 %s ", client->proxy_address, client->nick); @@ -281,9 +281,9 @@ void proxy_dump_data(CLIENT_REC *client) g_strfreev(paramlist); } - proxy_outdata(client, ":%s 251 %s :There are 0 users and 0 invisible on 1 servers\n", client->proxy_address, client->nick); - proxy_outdata(client, ":%s 255 %s :I have 0 clients, 0 services and 0 servers\n", client->proxy_address, client->nick); - proxy_outdata(client, ":%s 422 %s :MOTD File is missing\n", client->proxy_address, client->nick); + proxy_outdata(client, ":%s 251 %s :There are 0 users and 0 invisible on 1 servers\r\n", client->proxy_address, client->nick); + proxy_outdata(client, ":%s 255 %s :I have 0 clients, 0 services and 0 servers\r\n", client->proxy_address, client->nick); + proxy_outdata(client, ":%s 422 %s :MOTD File is missing\r\n", client->proxy_address, client->nick); /* user mode / away status */ if (client->server != NULL) { @@ -293,7 +293,7 @@ void proxy_dump_data(CLIENT_REC *client) client->server->usermode); } if (client->server->usermode_away) { - proxy_outdata(client, ":%s 306 %s :You have been marked as being away\n", + proxy_outdata(client, ":%s 306 %s :You have been marked as being away\r\n", client->proxy_address, client->nick); } diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 4c3bcf68..2b7c7bda 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -155,7 +155,7 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, if (*target == '\0' || g_ascii_strcasecmp(target, client->proxy_address) == 0 || g_ascii_strcasecmp(target, client->nick) == 0) { - proxy_outdata(client, ":%s PONG %s :%s\n", + proxy_outdata(client, ":%s PONG %s :%s\r\n", client->proxy_address, client->proxy_address, origin); g_free(params); @@ -174,18 +174,18 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, /* 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\n", + 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\n", + proxy_outdata(client, ":%s NOTICE %s :You're now receiving CTCPs sent to %s\r\n", 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->want_ctcp = 0; - proxy_outdata(client, ":%s NOTICE %s :Proxy is now handling itself CTCPs sent to %s\n", + 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); } else { signal_emit("proxy client command", 3, client, args, data); @@ -194,7 +194,7 @@ 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\n", + proxy_outdata(client, ":%s NOTICE %s :Not connected to server\r\n", client->proxy_address, client->nick); return; } @@ -371,7 +371,7 @@ static void sig_incoming(IRC_SERVER_REC *server, const char *line) g_return_if_fail(line != NULL); /* send server event to all clients */ - g_string_printf(next_line, "%s\n", line); + g_string_printf(next_line, "%s\r\n", line); } static void sig_server_event(IRC_SERVER_REC *server, const char *line, @@ -465,7 +465,7 @@ static void event_connected(IRC_SERVER_REC *server) (g_strcmp0(rec->listen->ircnet, "*") == 0 || (chatnet != NULL && g_ascii_strcasecmp(chatnet, rec->listen->ircnet) == 0))) { - proxy_outdata(rec, ":%s NOTICE %s :Connected to server\n", + proxy_outdata(rec, ":%s NOTICE %s :Connected to server\r\n", rec->proxy_address, rec->nick); rec->server = server; proxy_client_reset_nick(rec); @@ -478,7 +478,7 @@ static void proxy_server_disconnected(CLIENT_REC *client, { GSList *tmp; - proxy_outdata(client, ":%s NOTICE %s :Connection lost to server %s\n", + proxy_outdata(client, ":%s NOTICE %s :Connection lost to server %s\r\n", client->proxy_address, client->nick, server->connrec->address); From b0e7c183764e696b1e1a79c51651bc6573257bf8 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 20 Aug 2015 23:37:34 +0200 Subject: [PATCH 0101/1650] Send the CAP LS after sending the proxy strings Patch by @dequis --- src/irc/core/irc-servers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 335c88ef..58dc9b25 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -202,8 +202,6 @@ static void server_init(IRC_SERVER_REC *server) conn = server->connrec; - irc_send_cmd_now(server, "CAP LS"); - if (conn->proxy != NULL && conn->proxy_password != NULL && *conn->proxy_password != '\0') { cmd = g_strdup_printf("PASS %s", conn->proxy_password); @@ -217,6 +215,8 @@ static void server_init(IRC_SERVER_REC *server) g_free(cmd); } + irc_send_cmd_now(server, "CAP LS"); + if (conn->password != NULL && *conn->password != '\0') { /* send password */ cmd = g_strdup_printf("PASS %s", conn->password); From 0435331912f5d975c4cbef9b018bb89c07e610eb Mon Sep 17 00:00:00 2001 From: kyak Date: Wed, 26 Aug 2015 09:34:48 +0300 Subject: [PATCH 0102/1650] Clean up in hostname expando before return Clean up the vector resulting from g_strsplit before returning from expando_hostname(). Also, use g_strdup() instead of g_strconcat() to return the pointer to hostname. --- src/irc/core/irc-expandos.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c index cc46ece5..f26c9699 100644 --- a/src/irc/core/irc-expandos.c +++ b/src/irc/core/irc-expandos.c @@ -82,13 +82,16 @@ static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret) IRC_SERVER_REC *ircserver; char hostname[100]; char **list; + char *hostname_split; ircserver = IRC_SERVER(server); /* prefer the _real_ /userhost reply */ if (ircserver != NULL && ircserver->userhost != NULL) { list = g_strsplit(ircserver->userhost, "@", -1); - return list[1]; + hostname_split = g_strdup(list[1]); + g_strfreev(list); + return hostname_split; } /* haven't received userhost reply yet. guess something */ @@ -96,7 +99,7 @@ static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret) if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0') strcpy(hostname, "??"); - return g_strconcat(hostname, NULL); + return g_strdup(hostname); } /* user mode in active server */ From 19760679eb141baf3bff2110ee03aec90c653a2a Mon Sep 17 00:00:00 2001 From: kyak Date: Sat, 29 Aug 2015 15:29:57 +0300 Subject: [PATCH 0103/1650] In expando_hostname, set *free_ret to TRUE *free_ret must be set to TRUE in both cases, since we return some newly initialised memory --- src/irc/core/irc-expandos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c index f26c9699..4aa50c52 100644 --- a/src/irc/core/irc-expandos.c +++ b/src/irc/core/irc-expandos.c @@ -86,6 +86,8 @@ static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret) ircserver = IRC_SERVER(server); + *free_ret = TRUE; + /* prefer the _real_ /userhost reply */ if (ircserver != NULL && ircserver->userhost != NULL) { list = g_strsplit(ircserver->userhost, "@", -1); @@ -95,8 +97,6 @@ static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret) } /* haven't received userhost reply yet. guess something */ - *free_ret = TRUE; - if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0') strcpy(hostname, "??"); return g_strdup(hostname); From b7d82ecdcee3224ca5280977d0ffd7b5e0fb07d2 Mon Sep 17 00:00:00 2001 From: kyak Date: Sat, 29 Aug 2015 15:32:22 +0300 Subject: [PATCH 0104/1650] Use "(none)" as fallback for hostname and userhost expandos Use "(none)" instead of "??" for hostname and userhost expandos when these can't be reliably detected. --- src/irc/core/irc-expandos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c index 4aa50c52..df0326a2 100644 --- a/src/irc/core/irc-expandos.c +++ b/src/irc/core/irc-expandos.c @@ -72,7 +72,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret) username = ircserver->connrec->username; if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0') - strcpy(hostname, "??"); + strcpy(hostname, "(none)"); return g_strconcat(username, "@", hostname, NULL);; } @@ -98,7 +98,7 @@ static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret) /* haven't received userhost reply yet. guess something */ if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0') - strcpy(hostname, "??"); + strcpy(hostname, "(none)"); return g_strdup(hostname); } From b065f2a0112fe733878c17375d16cf12a3457e09 Mon Sep 17 00:00:00 2001 From: kyak Date: Sat, 29 Aug 2015 15:36:05 +0300 Subject: [PATCH 0105/1650] Use HOST_NAME_MAX for userhost and hostname expandos Use HOST_NAME_MAX instead of hardcoded 100 for userhost and hostname expandos. --- src/irc/core/irc-expandos.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c index df0326a2..9604c625 100644 --- a/src/irc/core/irc-expandos.c +++ b/src/irc/core/irc-expandos.c @@ -56,7 +56,8 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret) { IRC_SERVER_REC *ircserver; const char *username; - char hostname[100]; + char hostname[HOST_NAME_MAX]; + ircserver = IRC_SERVER(server); @@ -80,7 +81,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret) static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret) { IRC_SERVER_REC *ircserver; - char hostname[100]; + char hostname[HOST_NAME_MAX]; char **list; char *hostname_split; From 2f9cca8ec6e491759583c1de3bd74fbef0d6e2a1 Mon Sep 17 00:00:00 2001 From: kyak Date: Sat, 29 Aug 2015 15:40:17 +0300 Subject: [PATCH 0106/1650] Remove extra line break How did this extra break cripple in here? --- src/irc/core/irc-expandos.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c index 9604c625..5d8150f0 100644 --- a/src/irc/core/irc-expandos.c +++ b/src/irc/core/irc-expandos.c @@ -58,7 +58,6 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret) const char *username; char hostname[HOST_NAME_MAX]; - ircserver = IRC_SERVER(server); /* prefer the _real_ /userhost reply */ From 35d30c19a1fa5413a26a04885ed6cb05af4e2565 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 2 Sep 2015 20:24:47 +0200 Subject: [PATCH 0107/1650] Whitespace fix --- 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 c334e698..ebbbdcfa 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -262,7 +262,7 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, ignore_next = TRUE; if (*msg != '\001' || msg[strlen(msg)-1] != '\001') { - signal_emit(server_ischannel(SERVER(client->server), target) ? + signal_emit(server_ischannel(SERVER(client->server), target) ? "message own_public" : "message own_private", 4, client->server, msg, target, target); } else if (strncmp(msg+1, "ACTION ", 7) == 0) { From 57d645f24603e8c7d2cfe7098b3dbb1359cd8d22 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 2 Sep 2015 21:50:40 +0200 Subject: [PATCH 0108/1650] Introduce some more chantypes awareness --- src/fe-common/irc/fe-events.c | 11 ++++-- src/fe-common/irc/fe-irc-messages.c | 57 +++++++++++++++++++---------- 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c index ad5e7559..7f5a8c26 100644 --- a/src/fe-common/irc/fe-events.c +++ b/src/fe-common/irc/fe-events.c @@ -42,6 +42,9 @@ #include "fe-windows.h" #include "fe-irc-server.h" +int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target); +const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target); + static void event_privmsg(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { @@ -52,12 +55,14 @@ static void event_privmsg(IRC_SERVER_REC *server, const char *data, params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); if (nick == NULL) nick = server->real_address; if (addr == NULL) addr = ""; - if (*target == '@' && server_ischannel(SERVER(server), &target[1])) { + + if (fe_channel_is_opchannel(server, target)) { /* Hybrid 6 feature, send msg to all ops in channel */ - recoded = recode_in(SERVER(server), msg, target+1); + target = (char *)fe_channel_skip_prefix(server, target); + recoded = recode_in(SERVER(server), msg, target); signal_emit("message irc op_public", 5, server, recoded, nick, addr, - get_visible_target(server, target+1)); + get_visible_target(server, target)); } else { recoded = recode_in(SERVER(server), msg, server_ischannel(SERVER(server), target) ? target : nick); signal_emit(server_ischannel(SERVER(server), target) ? diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index 780c0b7e..e8cdb2c4 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -37,28 +37,47 @@ #include "fe-queries.h" #include "window-items.h" -static const char *skip_target(IRC_SERVER_REC *server, const char *target) +int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target) { - int i = 0; - const char *val, *chars; + const char *statusmsg; + + /* Quick check */ + if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0) + return FALSE; + + statusmsg = g_hash_table_lookup(server->isupport, "statusmsg"); + if (statusmsg == NULL) + statusmsg = "@+"; + + return strchr(statusmsg, *target) != NULL; +} + +const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target) +{ + const char *statusmsg; /* Quick check */ if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0) return target; + /* Exit early if target doesn't name a channel */ + if (server_ischannel(SERVER(server), target) == FALSE) + return FALSE; + + 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) */ - val = g_hash_table_lookup(server->isupport, "STATUSMSG"); - if (val == NULL && *target != '@') + if (statusmsg == NULL && *target != '@') return target; - chars = val ? val : "@+"; - for(i = 0; target[i] != '\0'; i++) { - if (strchr(chars, target[i]) == NULL) - break; - }; - if(server_ischannel(SERVER(server), &target[i])) - target += i; + if (statusmsg == NULL) + statusmsg = "@+"; + + /* Strip the leading statusmsg prefixes */ + while (strchr(statusmsg, *target) != NULL) { + target++; + } return target; } @@ -72,7 +91,7 @@ static void sig_message_own_public(SERVER_REC *server, const char *msg, if (!IS_IRC_SERVER(server)) return; oldtarget = target; - target = skip_target(IRC_SERVER(server), target); + target = fe_channel_skip_prefix(IRC_SERVER(server), target); if (target != oldtarget) { /* Hybrid 6 / Bahamut feature, send msg to all ops / ops+voices in channel */ @@ -135,7 +154,7 @@ static void sig_message_own_action(IRC_SERVER_REC *server, const char *msg, char *freemsg = NULL; oldtarget = target; - target = skip_target(IRC_SERVER(server), target); + target = fe_channel_skip_prefix(IRC_SERVER(server), target); if (server_ischannel(SERVER(server), target)) item = irc_channel_find(server, target); else @@ -163,7 +182,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, int own = FALSE; oldtarget = target; - target = skip_target(IRC_SERVER(server), target); + target = fe_channel_skip_prefix(IRC_SERVER(server), target); level = MSGLEVEL_ACTIONS | (server_ischannel(SERVER(server), target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS); @@ -219,7 +238,7 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, static void sig_message_own_notice(IRC_SERVER_REC *server, const char *msg, const char *target) { - printformat(server, skip_target(server, target), MSGLEVEL_NOTICES | + printformat(server, fe_channel_skip_prefix(server, target), MSGLEVEL_NOTICES | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT, IRCTXT_OWN_NOTICE, target, msg); } @@ -232,7 +251,7 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg, int level = MSGLEVEL_NOTICES; oldtarget = target; - target = skip_target(IRC_SERVER(server), target); + target = fe_channel_skip_prefix(IRC_SERVER(server), target); if (address == NULL || *address == '\0') { /* notice from server */ @@ -270,7 +289,7 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg, static void sig_message_own_ctcp(IRC_SERVER_REC *server, const char *cmd, const char *data, const char *target) { - printformat(server, skip_target(server, target), MSGLEVEL_CTCPS | + printformat(server, fe_channel_skip_prefix(server, target), MSGLEVEL_CTCPS | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT, IRCTXT_OWN_CTCP, target, cmd, data); } @@ -282,7 +301,7 @@ static void sig_message_irc_ctcp(IRC_SERVER_REC *server, const char *cmd, const char *oldtarget; oldtarget = target; - target = skip_target(server, target); + target = fe_channel_skip_prefix(server, target); printformat(server, server_ischannel(SERVER(server), target) ? target : nick, MSGLEVEL_CTCPS, IRCTXT_CTCP_REQUESTED, nick, addr, cmd, data, oldtarget); } From 21c1e4e9f80409b81cb3b8243c904ccf74d8d529 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 2 Sep 2015 22:40:10 +0200 Subject: [PATCH 0109/1650] Fix two minor issues outlined in the PR#222 irc-cap.c has now a licence header. A minor style fix in misc.c --- src/core/misc.c | 2 +- src/irc/core/irc-cap.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/core/misc.c b/src/core/misc.c index 395e47ad..88c27255 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -215,7 +215,7 @@ void gslist_free_full (GSList *list, GDestroyNotify free_func) { GSList *tmp; - if (!list) + if (list == NULL) return; for (tmp = list; tmp != NULL; tmp = tmp->next) diff --git a/src/irc/core/irc-cap.c b/src/irc/core/irc-cap.c index c5bf4e67..cd3ae677 100644 --- a/src/irc/core/irc-cap.c +++ b/src/irc/core/irc-cap.c @@ -1,3 +1,22 @@ +/* irc-cap.c : irssi + + Copyright (C) 2015 The Lemon Man + + 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 "misc.h" From b5b73cb471e5dff6f8c872071c7cb8678e4142ea Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 6 Sep 2015 15:47:08 +0200 Subject: [PATCH 0110/1650] Send smkx/rmkx sequence at terminal init Enter the "application" mode when setting up the terminal, this improves the compatiblity with the standards; as a side effect now DEL key works ootb when irssi is run in the suckless's st terminal. --- src/fe-text/terminfo-core.c | 107 ++++++++++++++++++++---------------- src/fe-text/terminfo-core.h | 4 ++ 2 files changed, 63 insertions(+), 48 deletions(-) diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c index 0516cc5f..6339e6f4 100644 --- a/src/fe-text/terminfo-core.c +++ b/src/fe-text/terminfo-core.c @@ -50,62 +50,66 @@ TERM_REC *current_term; /* Define only what we might need */ static TERMINFO_REC tcaps[] = { - /* Terminal size */ - { "cols", "co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, width) }, - { "lines", "li", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, height) }, + /* Terminal size */ + { "cols", "co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, width) }, + { "lines", "li", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, height) }, - /* Cursor movement */ - { "smcup", "ti", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smcup) }, - { "rmcup", "te", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmcup) }, - { "cup", "cm", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cup) }, - { "hpa", "ch", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_hpa) }, - { "vpa", "vh", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_vpa) }, - { "cub1", "le", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cub1) }, - { "cuf1", "nd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cuf1) }, - { "civis", "vi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_civis) }, - { "cnorm", "ve", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cnorm) }, + /* Cursor movement */ + { "smcup", "ti", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smcup) }, + { "rmcup", "te", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmcup) }, + { "cup", "cm", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cup) }, + { "hpa", "ch", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_hpa) }, + { "vpa", "vh", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_vpa) }, + { "cub1", "le", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cub1) }, + { "cuf1", "nd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cuf1) }, + { "civis", "vi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_civis) }, + { "cnorm", "ve", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_cnorm) }, - /* Scrolling */ - { "csr", "cs", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_csr) }, - { "wind", "wi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_wind) }, - { "ri", "sr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ri) }, - { "rin", "SR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rin) }, - { "ind", "sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ind) }, - { "indn", "SF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_indn) }, - { "il", "AL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il) }, - { "il1", "al", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il1) }, - { "dl", "DL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl) }, - { "dl1", "dl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl1) }, + /* Scrolling */ + { "csr", "cs", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_csr) }, + { "wind", "wi", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_wind) }, + { "ri", "sr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ri) }, + { "rin", "SR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rin) }, + { "ind", "sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ind) }, + { "indn", "SF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_indn) }, + { "il", "AL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il) }, + { "il1", "al", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_il1) }, + { "dl", "DL", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl) }, + { "dl1", "dl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_dl1) }, /* Clearing screen */ - { "clear", "cl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_clear) }, - { "ed", "cd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ed) }, + { "clear", "cl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_clear) }, + { "ed", "cd", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ed) }, - /* Clearing to end of line */ - { "el", "ce", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_el) }, + /* Clearing to end of line */ + { "el", "ce", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_el) }, - /* Repeating character */ - { "rep", "rp", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rep) }, + /* Repeating character */ + { "rep", "rp", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rep) }, /* Colors */ - { "colors", "Co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, TI_colors) }, - { "sgr0", "me", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sgr0) }, - { "smul", "us", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smul) }, - { "rmul", "ue", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmul) }, - { "smso", "so", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smso) }, - { "rmso", "se", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmso) }, - { "sitm", "ZH", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sitm) }, - { "ritm", "ZR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ritm) }, - { "bold", "md", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bold) }, - { "blink", "mb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_blink) }, - { "rev", "mr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rev) }, - { "setaf", "AF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setaf) }, - { "setab", "AB", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setab) }, - { "setf", "Sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setf) }, - { "setb", "Sb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setb) }, + { "colors", "Co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, TI_colors) }, + { "sgr0", "me", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sgr0) }, + { "smul", "us", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smul) }, + { "rmul", "ue", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmul) }, + { "smso", "so", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smso) }, + { "rmso", "se", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmso) }, + { "sitm", "ZH", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_sitm) }, + { "ritm", "ZR", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_ritm) }, + { "bold", "md", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bold) }, + { "blink", "mb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_blink) }, + { "rev", "mr", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rev) }, + { "setaf", "AF", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setaf) }, + { "setab", "AB", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setab) }, + { "setf", "Sf", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setf) }, + { "setb", "Sb", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_setb) }, - /* Beep */ - { "bel", "bl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bel) }, + /* Beep */ + { "bel", "bl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bel) }, + + /* Keyboard-transmit mode */ + { "smkx", "ks", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_smkx) }, + { "rmkx", "ke", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_rmkx) }, }; /* Move cursor (cursor_address / cup) */ @@ -523,7 +527,11 @@ static void terminfo_input_deinit(TERM_REC *term) void terminfo_cont(TERM_REC *term) { if (term->TI_smcup) - tput(tparm(term->TI_smcup)); + tput(tparm(term->TI_smcup)); + + if (term->TI_smkx) + tput(tparm(term->TI_smkx)); + terminfo_input_init(term); } @@ -538,6 +546,9 @@ void terminfo_stop(TERM_REC *term) if (term->TI_rmcup) tput(tparm(term->TI_rmcup)); + if (term->TI_rmkx) + tput(tparm(term->TI_rmkx)); + /* reset input settings */ terminfo_input_deinit(term); fflush(term->out); diff --git a/src/fe-text/terminfo-core.h b/src/fe-text/terminfo-core.h index 6ab4637d..21398791 100644 --- a/src/fe-text/terminfo-core.h +++ b/src/fe-text/terminfo-core.h @@ -88,6 +88,10 @@ struct _TERM_REC { /* Beep */ char *TI_bel; + + /* Keyboard-transmit mode */ + const char *TI_smkx; + const char *TI_rmkx; }; extern TERM_REC *current_term; From 4346c2a6d479b9c4d94fabc35ade324fdbe0e0d0 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 9 Sep 2015 23:55:00 +0200 Subject: [PATCH 0111/1650] Move the function prototypes in a separate header --- src/fe-common/irc/fe-common-irc.c | 4 +-- src/fe-common/irc/fe-events.c | 3 -- src/fe-common/irc/fe-irc-channels.c | 47 ++++++++++++++++++++++++++++- src/fe-common/irc/fe-irc-channels.h | 10 ++++++ src/fe-common/irc/fe-irc-messages.c | 45 --------------------------- 5 files changed, 57 insertions(+), 52 deletions(-) create mode 100644 src/fe-common/irc/fe-irc-channels.h diff --git a/src/fe-common/irc/fe-common-irc.c b/src/fe-common/irc/fe-common-irc.c index 72606263..d6ab30ce 100644 --- a/src/fe-common/irc/fe-common-irc.c +++ b/src/fe-common/irc/fe-common-irc.c @@ -28,13 +28,11 @@ #include "themes.h" #include "fe-irc-server.h" +#include "fe-irc-channels.h" void fe_irc_modules_init(void); void fe_irc_modules_deinit(void); -void fe_irc_channels_init(void); -void fe_irc_channels_deinit(void); - void fe_irc_queries_init(void); void fe_irc_queries_deinit(void); diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c index 7f5a8c26..068ee543 100644 --- a/src/fe-common/irc/fe-events.c +++ b/src/fe-common/irc/fe-events.c @@ -42,9 +42,6 @@ #include "fe-windows.h" #include "fe-irc-server.h" -int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target); -const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target); - static void event_privmsg(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { diff --git a/src/fe-common/irc/fe-irc-channels.c b/src/fe-common/irc/fe-irc-channels.c index 9129e451..d5f17bd0 100644 --- a/src/fe-common/irc/fe-irc-channels.c +++ b/src/fe-common/irc/fe-irc-channels.c @@ -31,6 +31,51 @@ #include "fe-windows.h" #include "window-items.h" +int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target) +{ + const char *statusmsg; + + /* Quick check */ + if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0) + return FALSE; + + statusmsg = g_hash_table_lookup(server->isupport, "statusmsg"); + if (statusmsg == NULL) + statusmsg = "@+"; + + return strchr(statusmsg, *target) != NULL; +} + +const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target) +{ + const char *statusmsg; + + /* Quick check */ + if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0) + return target; + + /* Exit early if target doesn't name a channel */ + if (server_ischannel(SERVER(server), target) == FALSE) + return FALSE; + + 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; + + if (statusmsg == NULL) + statusmsg = "@+"; + + /* Strip the leading statusmsg prefixes */ + while (strchr(statusmsg, *target) != NULL) { + target++; + } + + return target; +} + static void sig_channel_rejoin(SERVER_REC *server, REJOIN_REC *rec) { g_return_if_fail(rec != NULL); @@ -46,7 +91,7 @@ static void sig_event_forward(SERVER_REC *server, const char *data, char *params, *from, *to; params = event_get_params(data, 3, NULL, &from, &to); - if (from != NULL && to != NULL && server_ischannel(server, *from) && server_ischannel(server, *to)) { + if (from != NULL && to != NULL && server_ischannel(server, from) && server_ischannel(server, to)) { channel = irc_channel_find(server, from); if (channel != NULL && irc_channel_find(server, to) == NULL) { window_bind_add(window_item_window(channel), diff --git a/src/fe-common/irc/fe-irc-channels.h b/src/fe-common/irc/fe-irc-channels.h new file mode 100644 index 00000000..d05c91a5 --- /dev/null +++ b/src/fe-common/irc/fe-irc-channels.h @@ -0,0 +1,10 @@ +#ifndef __FE_IRC_CHANNELS_H +#define __FE_IRC_CHANNELS_H + +int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target); +const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target); + +void fe_irc_channels_init(void); +void fe_irc_channels_deinit(void); + +#endif diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index e8cdb2c4..b2736a2c 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -37,51 +37,6 @@ #include "fe-queries.h" #include "window-items.h" -int fe_channel_is_opchannel(IRC_SERVER_REC *server, const char *target) -{ - const char *statusmsg; - - /* Quick check */ - if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0) - return FALSE; - - statusmsg = g_hash_table_lookup(server->isupport, "statusmsg"); - if (statusmsg == NULL) - statusmsg = "@+"; - - return strchr(statusmsg, *target) != NULL; -} - -const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target) -{ - const char *statusmsg; - - /* Quick check */ - if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0) - return target; - - /* Exit early if target doesn't name a channel */ - if (server_ischannel(SERVER(server), target) == FALSE) - return FALSE; - - 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; - - if (statusmsg == NULL) - statusmsg = "@+"; - - /* Strip the leading statusmsg prefixes */ - while (strchr(statusmsg, *target) != NULL) { - target++; - } - - return target; -} - static void sig_message_own_public(SERVER_REC *server, const char *msg, const char *target, const char *origtarget) { From b8d3301d34f383f039071214872570385de1bb59 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 10 Sep 2015 01:02:44 +0200 Subject: [PATCH 0112/1650] SASL support The only supported methods are PLAIN and EXTERNAL, the latter is untested as of now. The code gets the values from the keys named sasl_{mechanism,username,password} specified for each chatnet. --- src/core/server-setup-rec.h | 3 + src/irc/core/Makefile.am | 2 + src/irc/core/irc-chatnets.c | 6 +- src/irc/core/irc-chatnets.h | 9 ++- src/irc/core/irc-core.c | 5 +- src/irc/core/irc-servers-setup.c | 24 ++++++ src/irc/core/irc-servers.c | 4 + src/irc/core/irc-servers.h | 4 + src/irc/core/sasl.c | 134 +++++++++++++++++++++++++++++++ src/irc/core/sasl.h | 14 ++++ 10 files changed, 200 insertions(+), 5 deletions(-) create mode 100644 src/irc/core/sasl.c create mode 100644 src/irc/core/sasl.h diff --git a/src/core/server-setup-rec.h b/src/core/server-setup-rec.h index ecdde3f3..2c9614c7 100644 --- a/src/core/server-setup-rec.h +++ b/src/core/server-setup-rec.h @@ -8,6 +8,9 @@ char *address; int port; char *password; +int sasl_mechanism; +char *sasl_password; + char *ssl_cert; char *ssl_pkey; char *ssl_pass; diff --git a/src/irc/core/Makefile.am b/src/irc/core/Makefile.am index 7d885d20..20caaeb1 100644 --- a/src/irc/core/Makefile.am +++ b/src/irc/core/Makefile.am @@ -27,6 +27,7 @@ libirc_core_a_SOURCES = \ irc-servers-setup.c \ irc-session.c \ irc-cap.c \ + sasl.c \ lag.c \ massjoin.c \ modes.c \ @@ -50,6 +51,7 @@ pkginc_irc_core_HEADERS = \ irc-servers.h \ irc-servers-setup.h \ irc-cap.h \ + sasl.h \ modes.h \ mode-lists.h \ module.h \ diff --git a/src/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c index d757bf8d..cfb7deec 100644 --- a/src/irc/core/irc-chatnets.c +++ b/src/irc/core/irc-chatnets.c @@ -48,6 +48,10 @@ static void sig_chatnet_read(IRC_CHATNET_REC *rec, CONFIG_NODE *node) rec->max_msgs = config_node_get_int(node, "max_msgs", 0); rec->max_modes = config_node_get_int(node, "max_modes", 0); rec->max_whois = config_node_get_int(node, "max_whois", 0); + + rec->sasl_mechanism = config_node_get_str(node, "sasl_mechanism", NULL); + rec->sasl_username = config_node_get_str(node, "sasl_username", NULL); + rec->sasl_password = config_node_get_str(node, "sasl_password", NULL); } static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node) @@ -78,7 +82,7 @@ static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node) static void sig_chatnet_destroyed(IRC_CHATNET_REC *rec) { if (IS_IRC_CHATNET(rec)) - g_free(rec->usermode); + g_free(rec->usermode); } diff --git a/src/irc/core/irc-chatnets.h b/src/irc/core/irc-chatnets.h index 22da90c5..2bb10fa9 100644 --- a/src/irc/core/irc-chatnets.h +++ b/src/irc/core/irc-chatnets.h @@ -17,12 +17,15 @@ struct _IRC_CHATNET_REC { #include "chatnet-rec.h" - char *usermode; + char *usermode; + + char *sasl_mechanism; + char *sasl_username; + char *sasl_password; int max_cmds_at_once; int cmd_queue_speed; - int max_query_chans; /* when syncing, max. number of channels to - put in one MODE/WHO command */ + int max_query_chans; /* when syncing, max. number of channels to put in one MODE/WHO command */ /* max. number of kicks/msgs/mode/whois per command */ int max_kicks, max_msgs, max_modes, max_whois; diff --git a/src/irc/core/irc-core.c b/src/irc/core/irc-core.c index e3ceeeef..a9221e02 100644 --- a/src/irc/core/irc-core.c +++ b/src/irc/core/irc-core.c @@ -27,6 +27,7 @@ #include "irc-channels.h" #include "irc-queries.h" #include "irc-cap.h" +#include "sasl.h" #include "irc-servers-setup.h" #include "channels-setup.h" @@ -119,6 +120,7 @@ void irc_core_init(void) netsplit_init(); irc_expandos_init(); cap_init(); + sasl_init(); settings_check(); module_register("core", "irc"); @@ -128,6 +130,7 @@ void irc_core_deinit(void) { signal_emit("chat protocol deinit", 1, chat_protocol_find("IRC")); + sasl_deinit(); cap_deinit(); irc_expandos_deinit(); netsplit_deinit(); @@ -140,7 +143,7 @@ void irc_core_deinit(void) irc_irc_deinit(); irc_servers_deinit(); irc_chatnets_deinit(); - irc_session_deinit(); + irc_session_deinit(); chat_protocol_unregister("IRC"); } diff --git a/src/irc/core/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c index 5659991b..9a9a8347 100644 --- a/src/irc/core/irc-servers-setup.c +++ b/src/irc/core/irc-servers-setup.c @@ -28,6 +28,7 @@ #include "irc-chatnets.h" #include "irc-servers-setup.h" #include "irc-servers.h" +#include "sasl.h" /* Fill information to connection from server setup record */ static void sig_server_setup_fill_reconn(IRC_SERVER_CONNECT_REC *conn, @@ -79,6 +80,29 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn, conn->cmd_queue_speed = ircnet->cmd_queue_speed; if (ircnet->max_query_chans > 0) conn->max_query_chans = ircnet->max_query_chans; + + /* Validate the SASL parameters filled by sig_chatnet_read() */ + conn->sasl_mechanism = SASL_MECHANISM_NONE; + + if (ircnet->sasl_mechanism != NULL) { + if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "plain")) { + /* The PLAIN method needs both the username and the password */ + if (ircnet->sasl_username != NULL && *ircnet->sasl_username && + ircnet->sasl_password != NULL && *ircnet->sasl_password) { + conn->sasl_mechanism = SASL_MECHANISM_PLAIN; + conn->sasl_username = ircnet->sasl_username; + conn->sasl_password = ircnet->sasl_password; + } else + g_warning("The fields sasl_username and sasl_password are either undefined or empty"); + } + else if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "external")) { + conn->sasl_mechanism = SASL_MECHANISM_EXTERNAL; + conn->sasl_username = NULL; + conn->sasl_password = NULL; + } + else + g_warning("Unsupported SASL mechanism \"%s\" selected", ircnet->sasl_mechanism); + } } static void init_userinfo(void) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index e9920d91..ad4d09cc 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -33,6 +33,7 @@ #include "irc-servers-setup.h" #include "irc-servers.h" #include "irc-cap.h" +#include "sasl.h" #include "channel-rejoin.h" #include "servers-idle.h" #include "servers-reconnect.h" @@ -215,6 +216,9 @@ static void server_init(IRC_SERVER_REC *server) g_free(cmd); } + if (conn->sasl_mechanism != SASL_MECHANISM_NONE) + cap_toggle(server, "sasl", TRUE); + irc_send_cmd_now(server, "CAP LS"); if (conn->password != NULL && *conn->password != '\0') { diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h index f809fab5..41c4b9c2 100644 --- a/src/irc/core/irc-servers.h +++ b/src/irc/core/irc-servers.h @@ -27,6 +27,10 @@ struct _IRC_SERVER_CONNECT_REC { char *usermode; char *alternate_nick; + int sasl_mechanism; + char *sasl_username; + char *sasl_password; + int max_cmds_at_once; int cmd_queue_speed; int max_query_chans; diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c new file mode 100644 index 00000000..8bffc3d9 --- /dev/null +++ b/src/irc/core/sasl.c @@ -0,0 +1,134 @@ +#include "module.h" +#include "misc.h" +#include "settings.h" + +#include "irc-cap.h" +#include "irc-servers.h" +#include "sasl.h" + +#define SASL_TIMEOUT (20 * 1000) // ms + +static gboolean sasl_timeout (IRC_SERVER_REC *server) +{ + /* The authentication timed out, we can't do much beside terminating it */ + g_critical("The authentication timed out, try increasing the timeout and check your connection " + "to the network."); + irc_send_cmd_now(server, "AUTHENTICATE *"); + cap_finish_negotiation(server); + + return G_SOURCE_REMOVE; +} + +static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *from) +{ + IRC_SERVER_CONNECT_REC *conn; + + conn = server->connrec; + + switch (conn->sasl_mechanism) { + case SASL_MECHANISM_PLAIN: + irc_send_cmd_now(server, "AUTHENTICATE PLAIN"); + break; + + case SASL_MECHANISM_EXTERNAL: + irc_send_cmd_now(server, "AUTHENTICATE EXTERNAL"); + break; + } + server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server); +} + +static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *from) +{ + /* Stop any pending timeout, if any */ + g_source_remove(server->sasl_timeout); + + g_critical("Authentication failed, make sure your credentials are correct and that the mechanism " + "you have selected is supported by this server."); + + /* Terminate the negotiation */ + cap_finish_negotiation(server); +} + +static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *from) +{ + g_source_remove(server->sasl_timeout); + + /* We're already authenticated, do nothing */ + cap_finish_negotiation(server); +} + +static void sasl_success (IRC_SERVER_REC *server, const char *data, const char *from) +{ + g_source_remove(server->sasl_timeout); + + /* The authentication succeeded, time to finish the CAP negotiation */ + g_warning("SASL authentication succeeded"); + cap_finish_negotiation(server); +} + +static void sasl_step (IRC_SERVER_REC *server, const char *data, const char *from) +{ + IRC_SERVER_CONNECT_REC *conn; + GString *req; + char *enc_req; + + conn = server->connrec; + + /* Stop the timer */ + g_source_remove(server->sasl_timeout); + + switch (conn->sasl_mechanism) { + case SASL_MECHANISM_PLAIN: + /* At this point we assume that conn->{username, password} are non-NULL. + * The PLAIN mechanism expects a NULL-separated string composed by the authorization identity, the + * authentication identity and the password. + * The authorization identity field is optional and can be omitted, the server will derive the + * identity by looking at the credentials provided. + * The whole request is then encoded in base64. */ + + req = g_string_new(NULL); + + g_string_append_c(req, '\0'); + g_string_append(req, conn->sasl_username); + g_string_append_c(req, '\0'); + g_string_append(req, conn->sasl_password); + + enc_req = g_base64_encode((const guchar *)req->str, req->len); + + irc_send_cmdv(server, "AUTHENTICATE %s", enc_req); + + g_free(enc_req); + g_string_free(req, TRUE); + break; + + case SASL_MECHANISM_EXTERNAL: + /* Empty response */ + irc_send_cmdv(server, "+"); + break; + } + + /* We expect a response within a reasonable time */ + server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server); +} + +void sasl_init(void) +{ + signal_add_first("server cap ack sasl", (SIGNAL_FUNC) sasl_start); + signal_add_first("event authenticate", (SIGNAL_FUNC) sasl_step); + signal_add_first("event 900", (SIGNAL_FUNC) sasl_success); + signal_add_first("event 902", (SIGNAL_FUNC) sasl_fail); + signal_add_first("event 904", (SIGNAL_FUNC) sasl_fail); + signal_add_first("event 905", (SIGNAL_FUNC) sasl_fail); + signal_add_first("event 907", (SIGNAL_FUNC) sasl_already); +} + +void sasl_deinit(void) +{ + signal_remove("server cap ack sasl", (SIGNAL_FUNC) sasl_start); + signal_remove("event authenticate", (SIGNAL_FUNC) sasl_step); + signal_remove("event 900", (SIGNAL_FUNC) sasl_success); + signal_remove("event 902", (SIGNAL_FUNC) sasl_fail); + signal_remove("event 904", (SIGNAL_FUNC) sasl_fail); + signal_remove("event 905", (SIGNAL_FUNC) sasl_fail); + signal_remove("event 907", (SIGNAL_FUNC) sasl_already); +} diff --git a/src/irc/core/sasl.h b/src/irc/core/sasl.h new file mode 100644 index 00000000..fcf87e16 --- /dev/null +++ b/src/irc/core/sasl.h @@ -0,0 +1,14 @@ +#ifndef __SASL_H +#define __SASL_H + +enum { + SASL_MECHANISM_NONE = 0, + SASL_MECHANISM_PLAIN, + SASL_MECHANISM_EXTERNAL, + SASL_MECHANISM_MAX +}; + +void sasl_init(void); +void sasl_deinit(void); + +#endif From c90c7deac37bea6754c9c2715230429fd49e8e81 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 11 Sep 2015 00:58:01 +0200 Subject: [PATCH 0113/1650] Address all the points outlined in the first review Replace G_SOURCE_REMOVE with FALSE for the compatibility sake. Zero the timeout id after g_source_remove and when exipred. Save the sasl_* options in sig_chatnet_saved(). --- src/irc/core/irc-chatnets.c | 9 ++++++++- src/irc/core/sasl.c | 24 +++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c index cfb7deec..b9b221b8 100644 --- a/src/irc/core/irc-chatnets.c +++ b/src/irc/core/irc-chatnets.c @@ -60,7 +60,7 @@ static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node) return; if (rec->usermode != NULL) - iconfig_node_set_str(node, "usermode", rec->usermode); + iconfig_node_set_str(node, "usermode", rec->usermode); if (rec->max_cmds_at_once > 0) iconfig_node_set_int(node, "cmdmax", rec->max_cmds_at_once); @@ -77,6 +77,13 @@ static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node) iconfig_node_set_int(node, "max_modes", rec->max_modes); if (rec->max_whois > 0) iconfig_node_set_int(node, "max_whois", rec->max_whois); + + if (rec->sasl_mechanism != NULL) + iconfig_node_set_str(node, "sasl_mechanism", rec->sasl_mechanism); + if (rec->sasl_username != NULL) + iconfig_node_set_str(node, "sasl_username", rec->sasl_username); + if (rec->sasl_password != NULL) + iconfig_node_set_str(node, "sasl_password", rec->sasl_password); } static void sig_chatnet_destroyed(IRC_CHATNET_REC *rec) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index 8bffc3d9..4b221176 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -16,7 +16,9 @@ static gboolean sasl_timeout (IRC_SERVER_REC *server) irc_send_cmd_now(server, "AUTHENTICATE *"); cap_finish_negotiation(server); - return G_SOURCE_REMOVE; + server->sasl_timeout = -1; + + return FALSE; } static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *from) @@ -40,7 +42,10 @@ static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *fr static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *from) { /* Stop any pending timeout, if any */ - g_source_remove(server->sasl_timeout); + if (server->sasl_timeout != -1) { + g_source_remove(server->sasl_timeout); + server->sasl_timeout = -1; + } g_critical("Authentication failed, make sure your credentials are correct and that the mechanism " "you have selected is supported by this server."); @@ -51,7 +56,10 @@ static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *fro static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *from) { - g_source_remove(server->sasl_timeout); + if (server->sasl_timeout != -1) { + g_source_remove(server->sasl_timeout); + server->sasl_timeout = -1; + } /* We're already authenticated, do nothing */ cap_finish_negotiation(server); @@ -59,7 +67,10 @@ static void sasl_already (IRC_SERVER_REC *server, const char *data, const char * static void sasl_success (IRC_SERVER_REC *server, const char *data, const char *from) { - g_source_remove(server->sasl_timeout); + if (server->sasl_timeout != -1) { + g_source_remove(server->sasl_timeout); + server->sasl_timeout = -1; + } /* The authentication succeeded, time to finish the CAP negotiation */ g_warning("SASL authentication succeeded"); @@ -75,7 +86,10 @@ static void sasl_step (IRC_SERVER_REC *server, const char *data, const char *fro conn = server->connrec; /* Stop the timer */ - g_source_remove(server->sasl_timeout); + if (server->sasl_timeout != -1) { + g_source_remove(server->sasl_timeout); + server->sasl_timeout = -1; + } switch (conn->sasl_mechanism) { case SASL_MECHANISM_PLAIN: From 171b67441d64a85a23daf5018159f167eb7fe583 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 11 Sep 2015 01:17:18 +0200 Subject: [PATCH 0114/1650] Replace spaces with tabs --- src/irc/core/sasl.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index 4b221176..0e343299 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -16,7 +16,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 = -1; return FALSE; } @@ -42,10 +42,10 @@ static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *fr static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *from) { /* Stop any pending timeout, if any */ - if (server->sasl_timeout != -1) { - g_source_remove(server->sasl_timeout); - server->sasl_timeout = -1; - } + if (server->sasl_timeout != -1) { + g_source_remove(server->sasl_timeout); + server->sasl_timeout = -1; + } g_critical("Authentication failed, make sure your credentials are correct and that the mechanism " "you have selected is supported by this server."); @@ -56,10 +56,10 @@ static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *fro static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *from) { - if (server->sasl_timeout != -1) { - g_source_remove(server->sasl_timeout); - server->sasl_timeout = -1; - } + if (server->sasl_timeout != -1) { + g_source_remove(server->sasl_timeout); + server->sasl_timeout = -1; + } /* We're already authenticated, do nothing */ cap_finish_negotiation(server); @@ -67,10 +67,10 @@ static void sasl_already (IRC_SERVER_REC *server, const char *data, const char * static void sasl_success (IRC_SERVER_REC *server, const char *data, const char *from) { - if (server->sasl_timeout != -1) { - g_source_remove(server->sasl_timeout); - server->sasl_timeout = -1; - } + if (server->sasl_timeout != -1) { + g_source_remove(server->sasl_timeout); + server->sasl_timeout = -1; + } /* The authentication succeeded, time to finish the CAP negotiation */ g_warning("SASL authentication succeeded"); @@ -86,10 +86,10 @@ static void sasl_step (IRC_SERVER_REC *server, const char *data, const char *fro conn = server->connrec; /* Stop the timer */ - if (server->sasl_timeout != -1) { - g_source_remove(server->sasl_timeout); - server->sasl_timeout = -1; - } + if (server->sasl_timeout != -1) { + g_source_remove(server->sasl_timeout); + server->sasl_timeout = -1; + } switch (conn->sasl_mechanism) { case SASL_MECHANISM_PLAIN: From 6645d0d38dc4627a9553235a98df4f4717a1fc6f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 11 Sep 2015 22:09:47 +0200 Subject: [PATCH 0115/1650] Explicitly set the authorization id during the PLAIN handshake On error show the user the message sent by the server. --- src/irc/core/sasl.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index 0e343299..4d52e3c0 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -47,8 +47,7 @@ static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *fro server->sasl_timeout = -1; } - g_critical("Authentication failed, make sure your credentials are correct and that the mechanism " - "you have selected is supported by this server."); + g_critical("Authentication failed with reason \"%s\"", data); /* Terminate the negotiation */ cap_finish_negotiation(server); @@ -93,15 +92,15 @@ static void sasl_step (IRC_SERVER_REC *server, const char *data, const char *fro switch (conn->sasl_mechanism) { case SASL_MECHANISM_PLAIN: - /* At this point we assume that conn->{username, password} are non-NULL. + /* At this point we assume that conn->sasl_{username, password} are non-NULL. * The PLAIN mechanism expects a NULL-separated string composed by the authorization identity, the * authentication identity and the password. - * The authorization identity field is optional and can be omitted, the server will derive the - * identity by looking at the credentials provided. + * The authorization identity field is explicitly set to the user provided username. * The whole request is then encoded in base64. */ req = g_string_new(NULL); + g_string_append(req, conn->sasl_username); g_string_append_c(req, '\0'); g_string_append(req, conn->sasl_username); g_string_append_c(req, '\0'); From 55387dd93df4cff349c5696ab1bcb87801f4443f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 11 Sep 2015 22:23:38 +0200 Subject: [PATCH 0116/1650] Handle event 906 and 908 --- src/irc/core/sasl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index 4d52e3c0..bf13dd21 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -132,7 +132,9 @@ void sasl_init(void) signal_add_first("event 902", (SIGNAL_FUNC) sasl_fail); signal_add_first("event 904", (SIGNAL_FUNC) sasl_fail); 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("event 908", (SIGNAL_FUNC) sasl_fail); } void sasl_deinit(void) @@ -143,5 +145,7 @@ void sasl_deinit(void) signal_remove("event 902", (SIGNAL_FUNC) sasl_fail); signal_remove("event 904", (SIGNAL_FUNC) sasl_fail); 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("event 908", (SIGNAL_FUNC) sasl_fail); } From 1f114d75c6db16726bcb930044b7312e4c851eaa Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 11 Sep 2015 23:17:46 +0200 Subject: [PATCH 0117/1650] Consider the SASL handshake successful on 903 --- src/irc/core/sasl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index bf13dd21..8f3b823f 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -128,7 +128,7 @@ void sasl_init(void) { signal_add_first("server cap ack sasl", (SIGNAL_FUNC) sasl_start); signal_add_first("event authenticate", (SIGNAL_FUNC) sasl_step); - signal_add_first("event 900", (SIGNAL_FUNC) sasl_success); + signal_add_first("event 903", (SIGNAL_FUNC) sasl_success); signal_add_first("event 902", (SIGNAL_FUNC) sasl_fail); signal_add_first("event 904", (SIGNAL_FUNC) sasl_fail); signal_add_first("event 905", (SIGNAL_FUNC) sasl_fail); @@ -141,7 +141,7 @@ void sasl_deinit(void) { signal_remove("server cap ack sasl", (SIGNAL_FUNC) sasl_start); signal_remove("event authenticate", (SIGNAL_FUNC) sasl_step); - signal_remove("event 900", (SIGNAL_FUNC) sasl_success); + signal_remove("event 903", (SIGNAL_FUNC) sasl_success); signal_remove("event 902", (SIGNAL_FUNC) sasl_fail); signal_remove("event 904", (SIGNAL_FUNC) sasl_fail); signal_remove("event 905", (SIGNAL_FUNC) sasl_fail); From 49c4ea5fd94c9eee17dc5a8e0691ba1da9bf33b7 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 11 Sep 2015 23:20:07 +0200 Subject: [PATCH 0118/1650] Parse the error string received by the server So that in case of SASL failure the user sees a nice error message. --- src/irc/core/sasl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index 8f3b823f..874b67f3 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -41,16 +41,22 @@ static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *fr 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) { g_source_remove(server->sasl_timeout); server->sasl_timeout = -1; } - g_critical("Authentication failed with reason \"%s\"", data); + params = event_get_params(data, 2, NULL, &error); + + g_critical("Authentication failed with reason \"%s\"", error); /* Terminate the negotiation */ cap_finish_negotiation(server); + + g_free(params); } static void sasl_already (IRC_SERVER_REC *server, const char *data, const char *from) From 24d32c28ee2d5dbd001cbe29fa5d90077c6be107 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 11 Sep 2015 23:21:33 +0200 Subject: [PATCH 0119/1650] Don't handle 908 as a critical failure "if the mechanism is unknown, 908 is optional, 904 (or equivalent error condition) is required" --- src/irc/core/sasl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index 874b67f3..56e80f48 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -140,7 +140,6 @@ 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("event 908", (SIGNAL_FUNC) sasl_fail); } void sasl_deinit(void) @@ -153,5 +152,4 @@ 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("event 908", (SIGNAL_FUNC) sasl_fail); } From 54a2fafbde593f63811da711c6a5f95ba58c818a Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Fri, 18 Sep 2015 23:33:52 +0200 Subject: [PATCH 0120/1650] Update perl.txt --- docs/perl.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/perl.txt b/docs/perl.txt index 79ab5820..560fcaec 100644 --- a/docs/perl.txt +++ b/docs/perl.txt @@ -1185,3 +1185,11 @@ Client->{} connected - whether the client is connected and ready want_ctcp - whether the client wants to receive CTCPs ircnet - network tag of the network we proxy + + + + + Bugs and Limitations + -------------------- +* Calling die in 'script error' handler causes segfault (#101) +* Storing and later using any Irssi object may result in use-after-free related crash From f37f6ac0edadf12476fba962d582bc43876f0be6 Mon Sep 17 00:00:00 2001 From: dequis Date: Fri, 18 Sep 2015 23:56:17 -0300 Subject: [PATCH 0121/1650] Add two missing #include "fe-irc-channels.h" Fixes #285 --- src/fe-common/irc/fe-events.c | 1 + src/fe-common/irc/fe-irc-messages.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c index 068ee543..3a01b9eb 100644 --- a/src/fe-common/irc/fe-events.c +++ b/src/fe-common/irc/fe-events.c @@ -41,6 +41,7 @@ #include "fe-queries.h" #include "fe-windows.h" #include "fe-irc-server.h" +#include "fe-irc-channels.h" static void event_privmsg(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index b2736a2c..11d158af 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -36,6 +36,7 @@ #include "fe-queries.h" #include "window-items.h" +#include "fe-irc-channels.h" static void sig_message_own_public(SERVER_REC *server, const char *msg, const char *target, const char *origtarget) From 061fb347502bd0b98f4587cfdce6612808d0c989 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 16 Sep 2015 15:31:51 +0200 Subject: [PATCH 0122/1650] Modify the terminal initialization sequence We disable the ICRNL flag to make Enter independent from ^J from the keybinding point of view since the former will now send ^M, leaving the user free to remap ^J without trapping itself into the irssi session because of a broken Enter key. Also disable the software flow control because we don't expect anyone to run irssi over a serial console; we gain some more freedom by having ^Q and ^S freely mappable by the user. --- src/fe-text/terminfo-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c index 6339e6f4..60927f1a 100644 --- a/src/fe-text/terminfo-core.c +++ b/src/fe-text/terminfo-core.c @@ -502,6 +502,9 @@ static void terminfo_input_init(TERM_REC *term) memcpy(&term->tio, &term->old_tio, sizeof(term->tio)); term->tio.c_lflag &= ~(ICANON | ECHO); /* CBREAK, no ECHO */ + /* Disable the ICRNL flag to disambiguate ^J and Enter, also disable the + * software flow control to leave ^Q and ^S ready to be bound */ + term->tio.c_iflag &= ~(ICRNL | IXON | IXOFF); term->tio.c_cc[VMIN] = 1; /* read() is satisfied after 1 char */ term->tio.c_cc[VTIME] = 0; /* No timer */ From 9586766d87820bdfa9e7cbe805f5ed4b7b0378e5 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Sat, 19 Sep 2015 18:27:48 -0300 Subject: [PATCH 0123/1650] Add setting to configure rejoin on reconnect behaviour Closes #169 --- src/irc/core/irc-servers.c | 50 ++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index b2718ae1..fdc5187f 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -33,6 +33,7 @@ #include "irc-servers-setup.h" #include "irc-servers.h" #include "irc-cap.h" +#include "channels-setup.h" #include "channel-rejoin.h" #include "servers-idle.h" #include "servers-reconnect.h" @@ -609,32 +610,59 @@ char *irc_server_get_channels(IRC_SERVER_REC *server) GString *chans, *keys; char *ret; int use_keys; + char *rejoin_channels_mode; g_return_val_if_fail(server != NULL, FALSE); + rejoin_channels_mode = g_strdup(settings_get_str("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"); + } + 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; - - g_string_append_printf(chans, "%s,", channel->name); - g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" : - channel->key); - if (channel->key != NULL) - use_keys = TRUE; + 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) { + g_string_append_printf(chans, "%s,", channel->name); + g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" : channel->key); + if (channel->key != NULL) + use_keys = TRUE; + } } /* get also the channels that are in rejoin list */ for (tmp = server->rejoin_channels; tmp != NULL; tmp = tmp->next) { REJOIN_REC *rec = tmp->data; + CHANNEL_SETUP_REC *setup = channel_setup_find(rec->channel, server->tag); - g_string_append_printf(chans, "%s,", rec->channel); - g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" : - rec->key); - if (rec->key != NULL) use_keys = TRUE; + if ((setup != NULL && setup->autojoin && g_ascii_strcasecmp(rejoin_channels_mode, "auto") == 0) || + g_ascii_strcasecmp(rejoin_channels_mode, "on") == 0) { + g_string_append_printf(chans, "%s,", rec->channel); + g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" : + rec->key); + + if (rec->key != NULL) use_keys = TRUE; + } } if (chans->len > 0) { @@ -646,6 +674,7 @@ 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; } @@ -991,6 +1020,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_str("misc", "usermode", DEFAULT_USER_MODE); settings_add_str("misc", "split_line_start", ""); settings_add_str("misc", "split_line_end", ""); From ca363efe00a05682acf9de828d55e991657b9e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sun, 20 Sep 2015 21:01:25 +0200 Subject: [PATCH 0124/1650] Use g_string_append() instead of g_string_append_c() for string. --- src/irc/proxy/dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/irc/proxy/dump.c b/src/irc/proxy/dump.c index 455a2fe3..05059360 100644 --- a/src/irc/proxy/dump.c +++ b/src/irc/proxy/dump.c @@ -169,7 +169,7 @@ static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client) NICK_REC *nick = tmp->data; if (str->len >= 500) { - g_string_append_c(str, '\r\n'); + g_string_append(str, "\r\n"); proxy_outdata(client, "%s", str->str); create_names_start(str, channel, client); first = TRUE; From 1079ad46d21198b26649c2a81a692781e22336aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sun, 20 Sep 2015 21:12:07 +0200 Subject: [PATCH 0125/1650] Use g_string_append() instead of g_string_append_c() for string. --- src/irc/proxy/dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/irc/proxy/dump.c b/src/irc/proxy/dump.c index 05059360..e39c21a6 100644 --- a/src/irc/proxy/dump.c +++ b/src/irc/proxy/dump.c @@ -186,7 +186,7 @@ static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client) } g_slist_free(nicks); - g_string_append_c(str, '\r\n'); + g_string_append(str, "\r\n"); proxy_outdata(client, "%s", str->str); g_string_free(str, TRUE); From be977bf1b795c93dbff4fa52f04b5d425a3f3648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sun, 20 Sep 2015 21:21:40 +0200 Subject: [PATCH 0126/1650] Fix warning. --- src/irc/core/irc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/irc/core/irc.c b/src/irc/core/irc.c index 509418b7..4dce3fcf 100644 --- a/src/irc/core/irc.c +++ b/src/irc/core/irc.c @@ -212,8 +212,12 @@ void irc_send_cmd_split(IRC_SERVER_REC *server, const char *cmd, count = 0; if (nickstr->len > 0) g_string_truncate(nickstr, nickstr->len-1); - irc_send_cmdv(server, post == NULL ? "%s %s" : "%s %s %s", - pre, nickstr->str, post); + + if (post == NULL) + irc_send_cmdv(server, "%s %s", pre, nickstr->str); + else + irc_send_cmdv(server, "%s %s %s", pre, nickstr->str, post); + g_string_truncate(nickstr, 0); if (*tmp == NULL || tmp[1] == NULL) From 29cf546ee4d5c1af1042d6fbeaae150ecc545d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sun, 20 Sep 2015 20:54:29 +0200 Subject: [PATCH 0127/1650] Remove Garbage Collection support. GC support was never enabled by default and nobody in the current development team seems to care about it. --- NEWS | 2 ++ acconfig.h | 3 --- configure.ac | 32 -------------------------------- src/common.h | 4 ---- src/fe-text/irssi.c | 23 ----------------------- 5 files changed, 2 insertions(+), 62 deletions(-) diff --git a/NEWS b/NEWS index d92f22e8..511f495a 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ v0.8.18-head 2014-XX-YY The Irssi team + + Garbage Collection support has been removed. This will hardly have any + effect for anyone given that it has been unsupported for several years. + Disable SSLv3 due to the POODLE vulnerability. + Try to split long lines on spaces to avoid words being splitted. Adds a new option: 'split_line_on_space' which defaults to on. diff --git a/acconfig.h b/acconfig.h index cfe62381..9ace70d8 100644 --- a/acconfig.h +++ b/acconfig.h @@ -3,9 +3,6 @@ #undef HAVE_SOCKS_H #undef HAVE_STATIC_PERL #undef HAVE_GMODULE -#undef HAVE_GC_H -#undef HAVE_GC_GC_H -#undef USE_GC /* macros/curses checks */ #undef HAS_CURSES diff --git a/configure.ac b/configure.ac index c312d065..e33b8c1d 100644 --- a/configure.ac +++ b/configure.ac @@ -83,15 +83,6 @@ if test "x$prefix" != "xNONE"; then perl_prefix_note=yes fi -AC_ARG_WITH(gc, -[ --with-gc Use garbage collector], - if test x$withval = xno; then - want_gc=no - else - want_gc=yes - fi, - want_gc=no) - AC_ARG_WITH(perl-staticlib, [ --with-perl-staticlib Specify that we want to link perl libraries statically in irssi, default is no], @@ -322,28 +313,6 @@ if test "$enable_ssl" = "yes"; then fi fi -dnl ** -dnl ** Garbage Collector -dnl ** -have_gc=no -if test "x$want_gc" = xyes; then - AC_CHECK_LIB(gc, GC_malloc, [ - AC_CHECK_HEADER(gc/gc.h, [ - AC_DEFINE(HAVE_GC_GC_H) - AC_DEFINE(USE_GC) - LIBS="$LIBS -lgc" - have_gc=yes - ], [ - AC_CHECK_HEADER(gc.h, [ - AC_DEFINE(HAVE_GC_H) - AC_DEFINE(USE_GC) - LIBS="$LIBS -lgc" - have_gc=yes - ]) - ]) - ]) -fi - dnl ** dnl ** curses checks dnl ** @@ -782,7 +751,6 @@ if test "x$have_openssl" = "xno" -a "x$enable_ssl" = "xyes"; then fi fi echo "Building with 64bit DCC support .. : $offt_64bit" -echo "Building with garbage collector .. : $have_gc" echo "Building with DANE support ....... : $have_dane" echo "Building with true color support.. : $want_truecolor" diff --git a/src/common.h b/src/common.h index 1b99753b..e9073925 100644 --- a/src/common.h +++ b/src/common.h @@ -56,10 +56,6 @@ #define g_strcmp0(a, b) (!a ? -(a != b) : (!b ? (a != b) : strcmp(a, b))) #endif -#ifdef USE_GC -# define g_free(x) G_STMT_START { (x) = NULL; } G_STMT_END -#endif - #if defined (UOFF_T_INT) typedef unsigned int uoff_t; #elif defined (UOFF_T_LONG) diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index 6d5b9b13..b1fa5e22 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -286,22 +286,6 @@ static void winsock_init(void) } #endif -#ifdef USE_GC -#ifdef HAVE_GC_H -# include -#else -# include -#endif - -GMemVTable gc_mem_table = { - GC_malloc, - GC_realloc, - GC_free, - - NULL, NULL, NULL -}; -#endif - int main(int argc, char **argv) { static int version = 0; @@ -312,10 +296,6 @@ int main(int argc, char **argv) }; int loglev; -#ifdef USE_GC - g_mem_set_vtable(&gc_mem_table); -#endif - core_register_options(); fe_common_core_register_options(); args_register(options); @@ -369,9 +349,6 @@ 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) { -#ifdef USE_GC - GC_collect_a_little(); -#endif if (!dummy) term_refresh_freeze(); g_main_iteration(TRUE); if (!dummy) term_refresh_thaw(); From 519955ebe4a421e8027c3dd09af9ea76d949d259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sun, 20 Sep 2015 21:45:33 +0200 Subject: [PATCH 0128/1650] Fix warning. Add comment on the use of ??) in C, since that string isn't entirely obvious to people who are reading the code. --- src/fe-text/statusbar-items.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/fe-text/statusbar-items.c b/src/fe-text/statusbar-items.c index 044c2fa0..e3e0c2a6 100644 --- a/src/fe-text/statusbar-items.c +++ b/src/fe-text/statusbar-items.c @@ -347,10 +347,14 @@ static void item_lag(SBAR_ITEM_REC *item, int get_size_only) last_lag_unknown = lag_unknown; if (lag_unknown) { - g_snprintf(str, sizeof(str), "%d (?""?)", lag/100); + // "??)" in C becomes ']' + // See: https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C + g_snprintf(str, sizeof(str), "%d (?""?)", lag / 100); } else { - g_snprintf(str, sizeof(str), - lag%100 == 0 ? "%d" : "%d.%02d", lag/100, lag%100); + if (lag % 100 == 0) + g_snprintf(str, sizeof(str), "%d", lag / 100); + else + g_snprintf(str, sizeof(str), "%d.%02d", lag / 100, lag % 100); } statusbar_item_default_handler(item, get_size_only, From 6c9dcffb5ef6b0f024f5ab6d335b69ef79e4daa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sun, 20 Sep 2015 22:51:13 +0200 Subject: [PATCH 0129/1650] Fix formatting warnings. --- src/irc/core/irc-commands.c | 40 ++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index f2cd49c0..47644753 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -170,8 +170,11 @@ static void cmd_part(const char *data, IRC_SERVER_REC *server, if (*msg != '\0') recoded = recode_out(SERVER(server), msg, channame); - irc_send_cmdv(server, ! recoded ? "PART %s" : "PART %s :%s", - channame, recoded); + + if (recoded == NULL) + irc_send_cmdv(server, "PART %s", channame); + else + irc_send_cmdv(server, "PART %s :%s", channame, recoded); g_free(recoded); cmd_params_free(free_arg); @@ -219,8 +222,12 @@ static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *ite if (*topic != '\0' || g_hash_table_lookup(optlist, "delete") != NULL) recoded = recode_out(SERVER(server), topic, channame); - irc_send_cmdv(server, recoded == NULL ? "TOPIC %s" : "TOPIC %s :%s", - channame, recoded); + + if (recoded == NULL) + irc_send_cmdv(server, "TOPIC %s", channame); + else + irc_send_cmdv(server, "TOPIC %s :%s", channame, recoded); + g_free(recoded); cmd_params_free(free_arg); @@ -279,14 +286,14 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server, char *channel, *rest; void *free_arg; - CMD_IRC_SERVER(server); + CMD_IRC_SERVER(server); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channel, &rest)) return; if (g_strcmp0(channel, "*") == 0 || *channel == '\0') { if (!IS_IRC_CHANNEL(item)) - cmd_param_error(CMDERR_NOT_JOINED); + cmd_param_error(CMDERR_NOT_JOINED); channel = IRC_CHANNEL(item)->name; } @@ -295,8 +302,11 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server, *channel = '\0'; } - irc_send_cmdv(server, *rest == '\0' ? "WHO %s" : "WHO %s %s", - channel, rest); + if (rest[0] == '\0') + irc_send_cmdv(server, "WHO %s", channel); + else + irc_send_cmdv(server, "WHO %s %s", channel, rest); + cmd_params_free(free_arg); } @@ -502,8 +512,11 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server) if (free_nick) g_free(nicks_redir); server->whowas_found = FALSE; - irc_send_cmdv(server, *rest == '\0' ? "WHOWAS %s" : - "WHOWAS %s %s", nicks, rest); + + if (rest[0] == '\0') + irc_send_cmdv(server, "WHOWAS %s", nicks); + else + irc_send_cmdv(server, "WHOWAS %s %s", nicks, rest); cmd_params_free(free_arg); } @@ -913,9 +926,12 @@ static void cmd_unsilence(const char *data, IRC_SERVER_REC *server) static void command_self(const char *data, IRC_SERVER_REC *server) { - CMD_IRC_SERVER(server); + CMD_IRC_SERVER(server); - irc_send_cmdv(server, *data == '\0' ? "%s" : "%s %s", current_command, data); + if (data[0] == '\0') + irc_send_cmdv(server, "%s", current_command); + else + irc_send_cmdv(server, "%s %s", current_command, data); } static void command_1self(const char *data, IRC_SERVER_REC *server) From 5c3ef84a0ba3cde0d9e2586fcb618d81851776f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sun, 20 Sep 2015 23:02:51 +0200 Subject: [PATCH 0130/1650] Undefine PACKAGE_VERSION before overwriting it. --- irssi-version.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/irssi-version.sh b/irssi-version.sh index 1e9eae34..1fc6a558 100755 --- a/irssi-version.sh +++ b/irssi-version.sh @@ -22,6 +22,7 @@ if echo "${VERSION}" | grep -q -- -head; then # Because the git tag won't yet include the next release we modify the git # describe output using the version defined from configure.ac. version="${new_version}-$(echo "${git_version}" | sed 's/^.*-[0-9]\+-//')" + echo "#undef PACKAGE_VERSION" echo "#define PACKAGE_VERSION \"${version}\"" fi fi From a44c4b82de44af9aec59c542f3212795ecc52b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= Date: Sun, 20 Sep 2015 23:11:39 +0200 Subject: [PATCH 0131/1650] More format warnings removed. --- src/fe-common/core/fe-common-core.c | 7 +++++-- src/irc/core/irc-channels.c | 12 +++++++----- src/irc/core/servers-redirect.c | 8 +++++--- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index a475f056..341902df 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -326,8 +326,11 @@ static void autoconnect_servers(void) if (autocon_server != NULL) { /* connect to specified server */ - str = g_strdup_printf(autocon_password == NULL ? "%s %d" : "%s %d %s", - autocon_server, autocon_port, autocon_password); + if (autocon_password == NULL) + str = g_strdup_printf("%s %d", autocon_server, autocon_port); + else + str = g_strdup_printf("%s %d %s", autocon_server, autocon_port, autocon_password); + signal_emit("command connect", 1, str); g_free(str); return; diff --git a/src/irc/core/irc-channels.c b/src/irc/core/irc-channels.c index add18acf..682be4c2 100644 --- a/src/irc/core/irc-channels.c +++ b/src/irc/core/irc-channels.c @@ -146,11 +146,13 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data, continue; } if (outchans->len > 0) { - g_string_truncate(outchans, outchans->len-1); - g_string_truncate(outkeys, outkeys->len-1); - irc_send_cmdv(IRC_SERVER(server), - use_keys ? "JOIN %s %s" : "JOIN %s", - outchans->str, outkeys->str); + g_string_truncate(outchans, outchans->len - 1); + g_string_truncate(outkeys, outkeys->len - 1); + + if (use_keys) + irc_send_cmdv(IRC_SERVER(server), "JOIN %s %s", outchans->str, outkeys->str); + else + irc_send_cmdv(IRC_SERVER(server), "JOIN %s", outchans->str); } cmdlen = 0; g_string_truncate(outchans,0); diff --git a/src/irc/core/servers-redirect.c b/src/irc/core/servers-redirect.c index f0a285df..aeb9c010 100644 --- a/src/irc/core/servers-redirect.c +++ b/src/irc/core/servers-redirect.c @@ -433,9 +433,11 @@ static void redirect_abort(IRC_SERVER_REC *server, REDIRECT_REC *rec) if (rec->aborted || !rec->destroyed) { /* emit the failure signal */ - str = g_strdup_printf(rec->failure_signal != NULL ? - "FAILED %s: %s" : "FAILED %s", - rec->cmd->name, rec->failure_signal); + if (rec->failure_signal != NULL) + str = g_strdup_printf("FAILED %s: %s", rec->cmd->name, rec->failure_signal); + else + str = g_strdup_printf("FAILED %s", rec->cmd->name); + rawlog_redirect(server->rawlog, str); g_free(str); From 203c00938acad1da4a91a2c21afdac4ede08572a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 20 Sep 2015 23:13:43 +0200 Subject: [PATCH 0132/1650] Use formats instead of g_warning Add some copyright headers here and there too. --- docs/signals.txt | 4 +++ src/fe-common/irc/Makefile.am | 1 + src/fe-common/irc/fe-common-irc.c | 5 ++++ src/fe-common/irc/fe-sasl.c | 48 ++++++++++++++++++++++++++++++ src/fe-common/irc/module-formats.c | 2 ++ src/fe-common/irc/module-formats.h | 2 ++ src/irc/core/irc-servers-setup.c | 2 +- src/irc/core/sasl.c | 43 +++++++++++++++++++------- src/irc/core/sasl.h | 20 +++++++++++++ 9 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 src/fe-common/irc/fe-sasl.c diff --git a/docs/signals.txt b/docs/signals.txt index 5c40ce77..8b71fd95 100644 --- a/docs/signals.txt +++ b/docs/signals.txt @@ -136,6 +136,10 @@ irc-cap.c "server cap nak ", SERVER_REC "server cap end", SERVER_REC +sasl.c + "server sasl failure", SERVER_REC, char *reason + "server sasl success", SERVER_REC + irc.c: "server event", SERVER_REC, char *data, char *sender_nick, char *sender_address diff --git a/src/fe-common/irc/Makefile.am b/src/fe-common/irc/Makefile.am index 463f145c..a5dd4c77 100644 --- a/src/fe-common/irc/Makefile.am +++ b/src/fe-common/irc/Makefile.am @@ -26,6 +26,7 @@ real_sources = \ fe-netsplit.c \ fe-common-irc.c \ fe-whois.c \ + fe-sasl.c \ irc-completion.c \ module-formats.c diff --git a/src/fe-common/irc/fe-common-irc.c b/src/fe-common/irc/fe-common-irc.c index d6ab30ce..4a3ef1d3 100644 --- a/src/fe-common/irc/fe-common-irc.c +++ b/src/fe-common/irc/fe-common-irc.c @@ -69,6 +69,9 @@ void fe_netjoin_deinit(void); void fe_whois_init(void); void fe_whois_deinit(void); +void fe_sasl_init(void); +void fe_sasl_deinit(void); + void irc_completion_init(void); void irc_completion_deinit(void); @@ -91,6 +94,7 @@ void fe_common_irc_init(void) fe_netsplit_init(); fe_netjoin_init(); fe_whois_init(); + fe_sasl_init(); irc_completion_init(); settings_check(); @@ -116,6 +120,7 @@ void fe_common_irc_deinit(void) fe_netsplit_deinit(); fe_netjoin_deinit(); fe_whois_deinit(); + fe_sasl_deinit(); irc_completion_deinit(); theme_unregister(); diff --git a/src/fe-common/irc/fe-sasl.c b/src/fe-common/irc/fe-sasl.c new file mode 100644 index 00000000..331b38b0 --- /dev/null +++ b/src/fe-common/irc/fe-sasl.c @@ -0,0 +1,48 @@ +/* + fe-sasl.c : irssi + + Copyright (C) 2015 The Lemon Man + + 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 "module-formats.h" +#include "signals.h" +#include "levels.h" + +#include "printtext.h" + +static void sig_sasl_success(IRC_SERVER_REC *server) +{ + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_SASL_SUCCESS); +} + +static void sig_sasl_failure(IRC_SERVER_REC *server, const char *reason) +{ + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_SASL_ERROR, reason); +} + +void fe_sasl_init(void) +{ + signal_add("server sasl success", (SIGNAL_FUNC) sig_sasl_success); + signal_add("server sasl failure", (SIGNAL_FUNC) sig_sasl_failure); +} + +void fe_sasl_deinit(void) +{ + signal_remove("server sasl success", (SIGNAL_FUNC) sig_sasl_success); + signal_remove("server sasl failure", (SIGNAL_FUNC) sig_sasl_failure); +} diff --git a/src/fe-common/irc/module-formats.c b/src/fe-common/irc/module-formats.c index 6eaf18e8..f7b074ec 100644 --- a/src/fe-common/irc/module-formats.c +++ b/src/fe-common/irc/module-formats.c @@ -44,6 +44,8 @@ FORMAT_REC fecommon_irc_formats[] = { { "setupserver_header", "%#Server Port Network Settings", 0 }, { "setupserver_line", "%#%|$[!20]0 $[5]1 $[10]2 $3", 4, { 0, 1, 0, 0 } }, { "setupserver_footer", "", 0 }, + { "sasl_success", "SASL authentication succeeded", 0 }, + { "sasl_error", "Cannot authenticate via SASL ($0)", 1, { 0 } }, /* ---- */ { NULL, "Channels", 0 }, diff --git a/src/fe-common/irc/module-formats.h b/src/fe-common/irc/module-formats.h index 34dd3efc..c45f4562 100644 --- a/src/fe-common/irc/module-formats.h +++ b/src/fe-common/irc/module-formats.h @@ -22,6 +22,8 @@ enum { IRCTXT_SETUPSERVER_HEADER, IRCTXT_SETUPSERVER_LINE, IRCTXT_SETUPSERVER_FOOTER, + IRCTXT_SASL_SUCCESS, + IRCTXT_SASL_ERROR, IRCTXT_FILL_2, diff --git a/src/irc/core/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c index 9a9a8347..f5e4f8f4 100644 --- a/src/irc/core/irc-servers-setup.c +++ b/src/irc/core/irc-servers-setup.c @@ -93,7 +93,7 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn, conn->sasl_username = ircnet->sasl_username; conn->sasl_password = ircnet->sasl_password; } else - g_warning("The fields sasl_username and sasl_password are either undefined or empty"); + g_warning("The fields sasl_username and sasl_password are either missing or empty"); } else if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "external")) { conn->sasl_mechanism = SASL_MECHANISM_EXTERNAL; diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index 56e80f48..a04eaf45 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -1,3 +1,23 @@ +/* + fe-sasl.c : irssi + + Copyright (C) 2015 The Lemon Man + + 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 "misc.h" #include "settings.h" @@ -8,20 +28,20 @@ #define SASL_TIMEOUT (20 * 1000) // ms -static gboolean sasl_timeout (IRC_SERVER_REC *server) +static gboolean sasl_timeout(IRC_SERVER_REC *server) { /* The authentication timed out, we can't do much beside terminating it */ - g_critical("The authentication timed out, try increasing the timeout and check your connection " - "to the network."); irc_send_cmd_now(server, "AUTHENTICATE *"); cap_finish_negotiation(server); server->sasl_timeout = -1; + signal_emit("server sasl failure", 2, server, "The authentication timed out"); + return FALSE; } -static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *from) +static void sasl_start(IRC_SERVER_REC *server, const char *data, const char *from) { IRC_SERVER_CONNECT_REC *conn; @@ -39,7 +59,7 @@ static void sasl_start (IRC_SERVER_REC *server, const char *data, const char *fr server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server); } -static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *from) +static void sasl_fail(IRC_SERVER_REC *server, const char *data, const char *from) { char *params, *error; @@ -51,7 +71,7 @@ static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *fro params = event_get_params(data, 2, NULL, &error); - g_critical("Authentication failed with reason \"%s\"", error); + signal_emit("server sasl fail", 2, server, error); /* Terminate the negotiation */ cap_finish_negotiation(server); @@ -59,30 +79,33 @@ static void sasl_fail (IRC_SERVER_REC *server, const char *data, const char *fro g_free(params); } -static void sasl_already (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) { g_source_remove(server->sasl_timeout); server->sasl_timeout = -1; } + signal_emit("server sasl success", 1, server); + /* We're already authenticated, do nothing */ cap_finish_negotiation(server); } -static void sasl_success (IRC_SERVER_REC *server, const char *data, const char *from) +static void sasl_success(IRC_SERVER_REC *server, const char *data, const char *from) { if (server->sasl_timeout != -1) { g_source_remove(server->sasl_timeout); server->sasl_timeout = -1; } + signal_emit("server sasl success", 1, server); + /* The authentication succeeded, time to finish the CAP negotiation */ - g_warning("SASL authentication succeeded"); cap_finish_negotiation(server); } -static void sasl_step (IRC_SERVER_REC *server, const char *data, const char *from) +static void sasl_step(IRC_SERVER_REC *server, const char *data, const char *from) { IRC_SERVER_CONNECT_REC *conn; GString *req; diff --git a/src/irc/core/sasl.h b/src/irc/core/sasl.h index fcf87e16..0693989d 100644 --- a/src/irc/core/sasl.h +++ b/src/irc/core/sasl.h @@ -1,3 +1,23 @@ +/* + fe-sasl.c : irssi + + Copyright (C) 2015 The Lemon Man + + 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. +*/ + #ifndef __SASL_H #define __SASL_H From ffaa890e99e2176ff3d2dec0ab5a8136e1e946ff Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 21 Sep 2015 13:54:13 +0200 Subject: [PATCH 0133/1650] Initial work to make irssi respect the resolved ip order Ip's aren't selected using random() anymore, also select the ip version by using getaddrinfo and some proper hints. --- src/core/chat-commands.c | 6 +-- src/core/chatnet-rec.h | 2 +- src/core/net-nonblock.c | 38 ++++--------- src/core/net-nonblock.h | 4 +- src/core/network.c | 98 ++++++---------------------------- src/core/network.h | 2 +- src/core/server-connect-rec.h | 2 +- src/core/server-setup-rec.h | 2 +- src/core/servers-reconnect.c | 10 ++-- src/core/servers-setup.c | 67 +++++++---------------- src/core/servers-setup.h | 2 +- src/core/servers.c | 66 +++++++---------------- src/core/servers.h | 3 +- src/fe-common/core/fe-server.c | 4 +- src/fe-common/irc/fe-ircnet.c | 4 +- src/irc/dcc/dcc.c | 4 +- src/irc/proxy/listen.c | 9 ++-- 17 files changed, 87 insertions(+), 236 deletions(-) diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 8e881679..9c28a1fc 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -128,10 +128,10 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, host = g_hash_table_lookup(optlist, "host"); if (host != NULL && *host != '\0') { - IPADDR ip4, ip6; + IPADDR ip; - if (net_gethostbyname(host, &ip4, &ip6) == 0) - server_connect_own_ip_save(conn, &ip4, &ip6); + if (net_gethostbyname(host, &ip) == 0) + server_connect_own_ip_save(conn, &ip); } cmd_params_free(free_arg); diff --git a/src/core/chatnet-rec.h b/src/core/chatnet-rec.h index e3ed8aa0..3044643a 100644 --- a/src/core/chatnet-rec.h +++ b/src/core/chatnet-rec.h @@ -9,4 +9,4 @@ char *realname; char *own_host; /* address to use when connecting this server */ char *autosendcmd; /* command to send after connecting to this ircnet */ -IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */ +IPADDR *own_ip; /* resolved own_address if not NULL */ diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c index e637e673..bc8c4b96 100644 --- a/src/core/net-nonblock.c +++ b/src/core/net-nonblock.c @@ -103,15 +103,12 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, srand(time(NULL)); memset(&rec, 0, sizeof(rec)); - rec.error = net_gethostbyname(addr, &rec.ip4, &rec.ip6); + rec.error = net_gethostbyname(addr, &rec.ip); if (rec.error == 0) { errorstr = NULL; if (reverse_lookup) { /* reverse lookup the IP, ignore any error */ - if (rec.ip4.family != 0) - net_gethostbyaddr(&rec.ip4, &rec.host4); - if (rec.ip6.family != 0) - net_gethostbyaddr(&rec.ip6, &rec.host6); + net_gethostbyaddr(&rec.ip, &rec.host); } } else { errorstr = net_gethosterror(rec.error); @@ -122,18 +119,11 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, if (rec.errlen != 0) g_io_channel_write_block(pipe, (void *) errorstr, rec.errlen); else { - if (rec.host4) { - len = strlen(rec.host4) + 1; + if (rec.host) { + len = strlen(rec.host) + 1; g_io_channel_write_block(pipe, (void *) &len, sizeof(int)); - g_io_channel_write_block(pipe, (void *) rec.host4, - len); - } - if (rec.host6) { - len = strlen(rec.host6) + 1; - g_io_channel_write_block(pipe, (void *) &len, - sizeof(int)); - g_io_channel_write_block(pipe, (void *) rec.host6, + g_io_channel_write_block(pipe, (void *) rec.host, len); } } @@ -154,8 +144,7 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec) rec->error = -1; rec->errorstr = NULL; - rec->host4 = NULL; - rec->host6 = NULL; + rec->host = NULL; #ifndef WIN32 fcntl(g_io_channel_unix_get_fd(pipe), F_SETFL, O_NONBLOCK); @@ -174,15 +163,10 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec) rec->errorstr = g_malloc0(rec->errlen+1); g_io_channel_read_block(pipe, rec->errorstr, rec->errlen); } else { - if (rec->host4) { + if (rec->host) { g_io_channel_read_block(pipe, &len, sizeof(int)); - rec->host4 = g_malloc0(len); - g_io_channel_read_block(pipe, rec->host4, len); - } - if (rec->host6) { - g_io_channel_read_block(pipe, &len, sizeof(int)); - rec->host6 = g_malloc0(len); - g_io_channel_read_block(pipe, rec->host6, len); + rec->host = g_malloc0(len); + g_io_channel_read_block(pipe, rec->host, len); } } @@ -227,7 +211,6 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe) { RESOLVED_IP_REC iprec; GIOChannel *handle; - IPADDR *ip; g_return_if_fail(rec != NULL); @@ -241,9 +224,8 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe) g_io_channel_shutdown(rec->pipes[1], TRUE, NULL); g_io_channel_unref(rec->pipes[1]); - ip = iprec.ip4.family != 0 ? &iprec.ip4 : &iprec.ip6; handle = iprec.error == -1 ? NULL : - net_connect_ip(ip, rec->port, rec->my_ip); + net_connect_ip(&iprec.ip, rec->port, rec->my_ip); g_free_not_null(rec->my_ip); diff --git a/src/core/net-nonblock.h b/src/core/net-nonblock.h index af5968c8..581536b3 100644 --- a/src/core/net-nonblock.h +++ b/src/core/net-nonblock.h @@ -4,12 +4,12 @@ #include "network.h" typedef struct { - IPADDR ip4, ip6; /* resolved ip addresses */ + IPADDR ip; /* resolved ip address */ int error; /* error, 0 = no error, -1 = error: */ int errlen; /* error text length */ char *errorstr; /* error string - dynamically allocated, you'll need to free() it yourself unless it's NULL */ - char *host4, *host6; /* dito */ + char *host; /* dito */ } RESOLVED_IP_REC; typedef struct { diff --git a/src/core/network.c b/src/core/network.c index bfaa47fb..303483c6 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -137,35 +137,14 @@ static int sin_get_port(union sockaddr_union *so) /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) { - IPADDR ip4, ip6, *ip; + IPADDR ip; g_return_val_if_fail(addr != NULL, NULL); - if (net_gethostbyname(addr, &ip4, &ip6) == -1) + if (net_gethostbyname(addr, &ip) == -1) return NULL; - if (my_ip == NULL) { - /* prefer IPv4 addresses */ - ip = ip4.family != 0 ? &ip4 : &ip6; - } else if (IPADDR_IS_V6(my_ip)) { - /* my_ip is IPv6 address, use it if possible */ - if (ip6.family != 0) - ip = &ip6; - else { - my_ip = NULL; - ip = &ip4; - } - } else { - /* my_ip is IPv4 address, use it if possible */ - if (ip4.family != 0) - ip = &ip4; - else { - my_ip = NULL; - ip = &ip6; - } - } - - return net_connect_ip(ip, port, my_ip); + return net_connect_ip(&ip, port, my_ip); } /* Connect to socket with ip address */ @@ -413,82 +392,35 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port) /* Get IP addresses for host, both IPv4 and IPv6 if possible. If ip->family is 0, the address wasn't found. Returns 0 = ok, others = error code for net_gethosterror() */ -int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) +int net_gethostbyname(const char *addr, IPADDR *ip) { -#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 + struct addrinfo hints, *ailist; + int ret; g_return_val_if_fail(addr != NULL, -1); - memset(ip4, 0, sizeof(IPADDR)); - memset(ip6, 0, sizeof(IPADDR)); + memset(ip, 0, sizeof(IPADDR)); -#ifdef HAVE_IPV6 memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; +#ifdef HAVE_IPV6 + hints.ai_family = AF_UNSPEC; +#else + hints.ai_family = AF_INET; +#endif + hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG); /* save error to host_error for later use */ ret = getaddrinfo(addr, NULL, &hints, &ailist); if (ret != 0) return ret; - /* count IPs */ - count_v4 = count_v6 = 0; - for (ai = ailist; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family == AF_INET) - count_v4++; - else if (ai->ai_family == AF_INET6) - count_v6++; - } - - if (count_v4 == 0 && count_v6 == 0) - return HOST_NOT_FOUND; /* shouldn't happen? */ - - /* if there are multiple addresses, return random one */ - use_v4 = count_v4 <= 1 ? 0 : rand() % count_v4; - use_v6 = count_v6 <= 1 ? 0 : rand() % count_v6; - - count_v4 = count_v6 = 0; - for (ai = ailist; ai != NULL; ai = ai->ai_next) { - so = (union sockaddr_union *) ai->ai_addr; - - if (ai->ai_family == AF_INET) { - if (use_v4 == count_v4) - sin_get_ip(so, ip4); - count_v4++; - } else if (ai->ai_family == AF_INET6) { - if (use_v6 == count_v6) - sin_get_ip(so, ip6); - count_v6++; - } - } + so = (const union sockaddr_union *)ailist->ai_addr; + sin_get_ip(so, ip); 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. diff --git a/src/core/network.h b/src/core/network.h index fa7e9675..ea8b3055 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -71,7 +71,7 @@ int net_transmit(GIOChannel *handle, const char *data, int len); /* Get IP addresses for host, both IPv4 and IPv6 if possible. If ip->family is 0, the address wasn't found. Returns 0 = ok, others = error code for net_gethosterror() */ -int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6); +int net_gethostbyname(const char *addr, IPADDR *ip); /* 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); diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h index 80c5761b..3f24e7d8 100644 --- a/src/core/server-connect-rec.h +++ b/src/core/server-connect-rec.h @@ -16,7 +16,7 @@ char *address; int port; char *chatnet; -IPADDR *own_ip4, *own_ip6; +IPADDR *own_ip; char *password; char *nick; diff --git a/src/core/server-setup-rec.h b/src/core/server-setup-rec.h index 2c9614c7..fbf49b2c 100644 --- a/src/core/server-setup-rec.h +++ b/src/core/server-setup-rec.h @@ -19,7 +19,7 @@ char *ssl_capath; char *ssl_ciphers; char *own_host; /* address to use when connecting this server */ -IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */ +IPADDR *own_ip; /* resolved own_address if not NULL */ time_t last_connect; /* to avoid reconnecting too fast.. */ diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index ae97ecd2..3ba18ad0 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -177,13 +177,9 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info) dest->username = g_strdup(src->username); dest->realname = g_strdup(src->realname); - if (src->own_ip4 != NULL) { - dest->own_ip4 = g_new(IPADDR, 1); - memcpy(dest->own_ip4, src->own_ip4, sizeof(IPADDR)); - } - if (src->own_ip6 != NULL) { - dest->own_ip6 = g_new(IPADDR, 1); - memcpy(dest->own_ip6, src->own_ip6, sizeof(IPADDR)); + if (src->own_ip != NULL) { + dest->own_ip = g_new(IPADDR, 1); + memcpy(dest->own_ip, src->own_ip, sizeof(IPADDR)); } dest->channels = g_strdup(src->channels); diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 90a447d4..e8506f0f 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -33,32 +33,22 @@ GSList *setupservers; static char *old_source_host; int source_host_ok; /* Use source_host_ip .. */ -IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */ +IPADDR source_host_ip; /* Resolved address */ -static void save_ips(IPADDR *ip4, IPADDR *ip6, - IPADDR **save_ip4, IPADDR **save_ip6) +static void save_ips(IPADDR *ip, IPADDR **save_ip) { - if (ip4->family == 0) - g_free_and_null(*save_ip4); + if (ip->family == 0) + g_free_and_null(*save_ip); else { - if (*save_ip4 == NULL) - *save_ip4 = g_new(IPADDR, 1); - memcpy(*save_ip4, ip4, sizeof(IPADDR)); - } - - if (ip6->family == 0) - g_free_and_null(*save_ip6); - else { - if (*save_ip6 == NULL) - *save_ip6 = g_new(IPADDR, 1); - memcpy(*save_ip6, ip6, sizeof(IPADDR)); + if (*save_ip == NULL) + *save_ip = g_new(IPADDR, 1); + memcpy(*save_ip, ip, sizeof(IPADDR)); } } static void get_source_host_ip(void) { const char *hostname; - IPADDR ip4, ip6; if (source_host_ok) return; @@ -66,28 +56,21 @@ static void get_source_host_ip(void) /* FIXME: This will block! */ hostname = settings_get_str("hostname"); source_host_ok = *hostname != '\0' && - net_gethostbyname(hostname, &ip4, &ip6) == 0; - - if (source_host_ok) - save_ips(&ip4, &ip6, &source_host_ip4, &source_host_ip6); - else { - g_free_and_null(source_host_ip4); - g_free_and_null(source_host_ip6); - } + net_gethostbyname(hostname, &source_host_ip) == 0; } static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host, - IPADDR **own_ip4, IPADDR **own_ip6) + IPADDR **own_ip) { - IPADDR ip4, ip6; + IPADDR ip; - if (*own_ip4 == NULL && *own_ip6 == NULL) { + if (*own_ip == NULL) { /* resolve the IP */ - if (net_gethostbyname(own_host, &ip4, &ip6) == 0) - save_ips(&ip4, &ip6, own_ip4, own_ip6); + if (net_gethostbyname(own_host, &ip) == 0) + save_ips(&ip, own_ip); } - server_connect_own_ip_save(conn, *own_ip4, *own_ip6); + server_connect_own_ip_save(conn, *own_ip); } /* Fill information to connection from server setup record */ @@ -98,8 +81,7 @@ void server_setup_fill_reconn(SERVER_CONNECT_REC *conn, g_return_if_fail(IS_SERVER_SETUP(sserver)); if (sserver->own_host != NULL) { - conn_set_ip(conn, sserver->own_host, - &sserver->own_ip4, &sserver->own_ip6); + conn_set_ip(conn, sserver->own_host, &sserver->own_ip); } if (sserver->chatnet != NULL && conn->chatnet == NULL) @@ -139,13 +121,9 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn, } /* source IP */ - if (source_host_ip4 != NULL) { - conn->own_ip4 = g_new(IPADDR, 1); - memcpy(conn->own_ip4, source_host_ip4, sizeof(IPADDR)); - } - if (source_host_ip6 != NULL) { - conn->own_ip6 = g_new(IPADDR, 1); - memcpy(conn->own_ip6, source_host_ip6, sizeof(IPADDR)); + if (source_host_ok) { + conn->own_ip = g_new(IPADDR, 1); + memcpy(conn->own_ip, &source_host_ip, sizeof(IPADDR)); } signal_emit("server setup fill connect", 1, conn); @@ -206,8 +184,7 @@ static void server_setup_fill_chatnet(SERVER_CONNECT_REC *conn, conn->realname = g_strdup(chatnet->realname);; } if (chatnet->own_host != NULL) { - conn_set_ip(conn, chatnet->own_host, - &chatnet->own_ip4, &chatnet->own_ip6); + conn_set_ip(conn, chatnet->own_host, &chatnet->own_ip); } signal_emit("server setup fill chatnet", 2, conn, chatnet); @@ -481,8 +458,7 @@ static void server_setup_destroy(SERVER_SETUP_REC *rec) signal_emit("server setup destroyed", 1, rec); g_free_not_null(rec->own_host); - g_free_not_null(rec->own_ip4); - g_free_not_null(rec->own_ip6); + g_free_not_null(rec->own_ip); g_free_not_null(rec->chatnet); g_free_not_null(rec->password); g_free_not_null(rec->ssl_cert); @@ -556,7 +532,6 @@ void servers_setup_init(void) settings_add_str("proxy", "proxy_password", ""); setupservers = NULL; - source_host_ip4 = source_host_ip6 = NULL; old_source_host = NULL; read_settings(); @@ -567,8 +542,6 @@ void servers_setup_init(void) void servers_setup_deinit(void) { - g_free_not_null(source_host_ip4); - g_free_not_null(source_host_ip6); g_free_not_null(old_source_host); while (setupservers != NULL) diff --git a/src/core/servers-setup.h b/src/core/servers-setup.h index f7601a68..c4878094 100644 --- a/src/core/servers-setup.h +++ b/src/core/servers-setup.h @@ -16,7 +16,7 @@ struct _SERVER_SETUP_REC { extern GSList *setupservers; -extern IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */ +extern IPADDR source_host_ip; /* Resolved address */ extern int source_host_ok; /* Use source_host_ip .. */ /* Fill reconnection specific information to connection diff --git a/src/core/servers.c b/src/core/servers.c index 3342304e..e18f8d9c 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -218,7 +218,7 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip, return; if (ip != NULL) { - own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4; + own_ip = server->connrec->own_ip; port = server->connrec->proxy != NULL ? server->connrec->proxy_port : server->connrec->port; handle = server->connrec->use_ssl ? @@ -280,30 +280,15 @@ static void server_connect_callback_readpipe(SERVER_REC *server) server->connect_pipe[0] = NULL; server->connect_pipe[1] = NULL; - /* figure out if we should use IPv4 or v6 address */ - if (iprec.error != 0) { - /* error */ - ip = NULL; - } else if (server->connrec->family == AF_INET) { - /* force IPv4 connection */ - ip = iprec.ip4.family == 0 ? NULL : &iprec.ip4; - servername = iprec.host4; - } else if (server->connrec->family == AF_INET6) { - /* force IPv6 connection */ - ip = iprec.ip6.family == 0 ? NULL : &iprec.ip6; - servername = iprec.host6; - } else { - /* pick the one that was found, or if both do it like - /SET resolve_prefer_ipv6 says. */ - if (iprec.ip4.family == 0 || - (iprec.ip6.family != 0 && - settings_get_bool("resolve_prefer_ipv6"))) { - ip = &iprec.ip6; - servername = iprec.host6; - } else { - ip = &iprec.ip4; - servername = iprec.host4; - } + ip = NULL; + + if (iprec.error == 0) { + // FIXME : REMOVE THIS BEFORE MERGE + if (server->connrec->family) + g_assert(server->connrec->family == iprec.ip.family); + + ip = &iprec.ip; + servername = iprec.host; } if (ip != NULL) { @@ -337,8 +322,7 @@ static void server_connect_callback_readpipe(SERVER_REC *server) } g_free(iprec.errorstr); - g_free(iprec.host4); - g_free(iprec.host6); + g_free(iprec.host); } SERVER_REC *server_connect(SERVER_CONNECT_REC *conn) @@ -623,8 +607,7 @@ void server_connect_unref(SERVER_CONNECT_REC *conn) g_free_not_null(conn->address); g_free_not_null(conn->chatnet); - g_free_not_null(conn->own_ip4); - g_free_not_null(conn->own_ip6); + g_free_not_null(conn->own_ip); g_free_not_null(conn->password); g_free_not_null(conn->nick); @@ -654,26 +637,15 @@ void server_change_nick(SERVER_REC *server, const char *nick) } /* Update own IPv4 and IPv6 records */ -void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, - IPADDR *ip4, IPADDR *ip6) +void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, IPADDR *ip) { - if (ip4 == NULL || ip4->family == 0) - g_free_and_null(conn->own_ip4); - if (ip6 == NULL || ip6->family == 0) - g_free_and_null(conn->own_ip6); + if (ip == NULL || ip->family == 0) + g_free_and_null(conn->own_ip); - if (ip4 != NULL && ip4->family != 0) { - /* IPv4 address was found */ - if (conn->own_ip4 == NULL) - conn->own_ip4 = g_new0(IPADDR, 1); - memcpy(conn->own_ip4, ip4, sizeof(IPADDR)); - } - - if (ip6 != NULL && ip6->family != 0) { - /* IPv6 address was found */ - if (conn->own_ip6 == NULL) - conn->own_ip6 = g_new0(IPADDR, 1); - memcpy(conn->own_ip6, ip6, sizeof(IPADDR)); + if (ip != NULL && ip->family != 0) { + if (conn->own_ip == NULL) + conn->own_ip = g_new0(IPADDR, 1); + memcpy(conn->own_ip, ip, sizeof(IPADDR)); } } diff --git a/src/core/servers.h b/src/core/servers.h index f39c650b..314faa32 100644 --- a/src/core/servers.h +++ b/src/core/servers.h @@ -67,8 +67,7 @@ void server_connect_failed(SERVER_REC *server, const char *msg); void server_change_nick(SERVER_REC *server, const char *nick); /* Update own IPv4 and IPv6 records */ -void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, - IPADDR *ip4, IPADDR *ip6); +void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, IPADDR *ip); /* `optlist' should contain only one unknown key - the server tag. returns NULL if there was unknown -option */ diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index 429e6dac..f8558ad1 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(const char *data) if (*password != '\0') g_free_and_null(rec->password); if (g_hash_table_lookup(optlist, "host")) { g_free_and_null(rec->own_host); - rec->own_ip4 = rec->own_ip6 = NULL; + rec->own_ip = NULL; } } @@ -193,7 +193,7 @@ static void cmd_server_add(const char *data) value = g_hash_table_lookup(optlist, "host"); if (value != NULL && *value != '\0') { rec->own_host = g_strdup(value); - rec->own_ip4 = rec->own_ip6 = NULL; + rec->own_ip = NULL; } signal_emit("server add fill", 2, rec, optlist); diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index 6618edd7..4071f367 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -108,7 +108,7 @@ static void cmd_network_add(const char *data) if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname); if (g_hash_table_lookup(optlist, "host")) { g_free_and_null(rec->own_host); - rec->own_ip4 = rec->own_ip6 = NULL; + rec->own_ip = NULL; } if (g_hash_table_lookup(optlist, "usermode")) g_free_and_null(rec->usermode); if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd); @@ -140,7 +140,7 @@ static void cmd_network_add(const char *data) value = g_hash_table_lookup(optlist, "host"); if (value != NULL && *value != '\0') { rec->own_host = g_strdup(value); - rec->own_ip4 = rec->own_ip6 = NULL; + rec->own_ip = NULL; } value = g_hash_table_lookup(optlist, "usermode"); diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index 17f6c477..7fef2ae5 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -264,12 +264,12 @@ GIOChannel *dcc_connect_ip(IPADDR *ip, int port) } if (own_ip == NULL) - own_ip = IPADDR_IS_V6(ip) ? source_host_ip6 : source_host_ip4; + own_ip = &source_host_ip; handle = net_connect_ip(ip, port, own_ip); if (handle == NULL && errno == EADDRNOTAVAIL && own_ip != NULL) { /* dcc_own_ip is external address */ - own_ip = IPADDR_IS_V6(ip) ? source_host_ip6 : source_host_ip4; + own_ip = &source_host_ip; handle = net_connect_ip(ip, port, own_ip); } return handle; diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index dcc94e6b..16950c79 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -585,7 +585,7 @@ static LISTEN_REC *find_listen(const char *ircnet, int port) static void add_listen(const char *ircnet, int port) { LISTEN_REC *rec; - IPADDR ip4, ip6, *my_ip; + IPADDR ip, *my_ip; if (port <= 0 || *ircnet == '\0') return; @@ -593,16 +593,13 @@ static void add_listen(const char *ircnet, int port) /* 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) { + if (net_gethostbyname(settings_get_str("irssiproxy_bind"), &ip) != 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 = &ip; } rec = g_new0(LISTEN_REC, 1); From 564829610de20f75ec667f1943524c3a49b9ea3f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 21 Sep 2015 14:38:10 +0200 Subject: [PATCH 0134/1650] Ding dong the switch is dead --- docs/help/in/toggle.in | 2 +- docs/manual.txt | 3 --- src/core/servers.c | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/help/in/toggle.in b/docs/help/in/toggle.in index f87a6462..71f5c8f4 100644 --- a/docs/help/in/toggle.in +++ b/docs/help/in/toggle.in @@ -15,7 +15,7 @@ %9Examples:%9 - /TOGGLE resolve_prefer_ipv6 + /TOGGLE resolve_reverse_lookup /TOGGLE channels_rejoin_unavailable ON %9See also:%9 SET diff --git a/docs/manual.txt b/docs/manual.txt index b2d0de14..12d8031e 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -429,9 +429,6 @@ After connected to server, Irssi can automatically change your user mode. You can set it with /SET usermode , default is +i. - /SET resolve_prefer_ipv6 - If ON, prefer IPv6 for hosts that - have both v4 and v6 addresses. - 5.5 Automatic reconnecting If you get disconnected from server, Irssi will try to reconnect diff --git a/src/core/servers.c b/src/core/servers.c index e18f8d9c..66060a7f 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -710,7 +710,6 @@ static void sig_chat_protocol_deinit(CHAT_PROTOCOL_REC *proto) void servers_init(void) { - settings_add_bool("server", "resolve_prefer_ipv6", FALSE); settings_add_bool("server", "resolve_reverse_lookup", FALSE); lookup_servers = servers = NULL; From f39723f6510bf57c5d21d62d55be6eefb6305078 Mon Sep 17 00:00:00 2001 From: dequis Date: Thu, 17 Sep 2015 00:55:31 -0300 Subject: [PATCH 0135/1650] Fix FS#905, mangled text when pasted line length exceeds 400 http://bugs.irssi.org/index.php?do=details&task_id=905 Not using the patch from that ticket, the issue turned out to be that (dest - last_lf_pos) returned number of unichr, not bytes, so that's 4 times less than what the size parameter of memmove() should be. --- src/fe-text/gui-readline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index edc4c55d..ec61e317 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -237,7 +237,7 @@ static void paste_buffer_join_lines(GArray *buf) last_lf = FALSE; if (++line_len >= 400 && last_lf_pos != NULL) { memmove(last_lf_pos+1, last_lf_pos, - dest - last_lf_pos); + (dest - last_lf_pos) * sizeof(unichar)); *last_lf_pos = '\n'; last_lf_pos = NULL; line_len = 0; dest++; From 0823289fd9c6a2eec7ff04581426856d1dbb15e5 Mon Sep 17 00:00:00 2001 From: dequis Date: Mon, 21 Sep 2015 22:53:53 -0300 Subject: [PATCH 0136/1650] Limit recursion depth of key/combo expansion in key_states_scan() Fixes FS#817 - "SegFault when executing bind command", which provides the test case "/bind cleft key meta", which is stupid but now it doesn't break things. The limit of 100 is arbitrary, it means roughly 140 stack frames total. The flyspray ticket mentions it crashes at 512, in my system it goes all the way to 149677 stack frames. http://bugs.irssi.org/index.php?do=details&task_id=817 --- src/fe-common/core/keyboard.c | 37 ++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/fe-common/core/keyboard.c b/src/fe-common/core/keyboard.c index f138d4e2..fed7f9cb 100644 --- a/src/fe-common/core/keyboard.c +++ b/src/fe-common/core/keyboard.c @@ -31,6 +31,8 @@ #include "fe-windows.h" #include "printtext.h" +#define MAX_EXPAND_RECURSION 100 + GSList *keyinfos; static GHashTable *keys, *default_keys; @@ -171,7 +173,7 @@ KEYINFO_REC *key_info_find(const char *id) return NULL; } -static int expand_key(const char *key, GSList **out); +static int expand_key(const char *key, GSList **out, int *limit); #define expand_out_char(out, c) \ { \ @@ -188,13 +190,17 @@ static int expand_key(const char *key, GSList **out); g_slist_free(out); out = NULL; \ } -static int expand_combo(const char *start, const char *end, GSList **out) +static int expand_combo(const char *start, const char *end, GSList **out, int *limit) { KEY_REC *rec; KEYINFO_REC *info; GSList *tmp, *tmp2, *list, *copy, *newout; char *str, *p; + if ((*limit)-- < 0) { + return FALSE; + } + if (start == end) { /* single key */ expand_out_char(*out, *start); @@ -229,7 +235,7 @@ static int expand_combo(const char *start, const char *end, GSList **out) /* only one way to generate the combo, good */ rec = list->data; g_slist_free(list); - return expand_key(rec->key, out); + return expand_key(rec->key, out, limit); } /* multiple ways to generate the combo - @@ -244,7 +250,11 @@ static int expand_combo(const char *start, const char *end, GSList **out) copy = g_slist_append(copy, g_string_new(str->str)); } - if (!expand_key(rec->key, ©)) { + if (!expand_key(rec->key, ©, limit)) { + if (*limit < 0) { + return FALSE; + } + /* illegal key combo, remove from list */ expand_out_free(copy); } else { @@ -254,7 +264,11 @@ static int expand_combo(const char *start, const char *end, GSList **out) rec = list->data; g_slist_free(list); - if (!expand_key(rec->key, out)) { + if (!expand_key(rec->key, out, limit)) { + if (*limit < 0) { + return FALSE; + } + /* illegal key combo, remove from list */ expand_out_free(*out); } @@ -264,12 +278,16 @@ static int expand_combo(const char *start, const char *end, GSList **out) } /* Expand key code - returns TRUE if successful. */ -static int expand_key(const char *key, GSList **out) +static int expand_key(const char *key, GSList **out, int *limit) { GSList *tmp; const char *start; int last_hyphen; + if ((*limit)-- < 0) { + return FALSE; + } + /* meta-^W^Gf -> ^[-^W-^G-f */ start = NULL; last_hyphen = TRUE; for (; *key != '\0'; key++) { @@ -279,7 +297,7 @@ static int expand_key(const char *key, GSList **out) continue; } - if (!expand_combo(start, key-1, out)) + if (!expand_combo(start, key-1, out, limit)) return FALSE; expand_out_char(*out, '-'); start = NULL; @@ -332,7 +350,7 @@ static int expand_key(const char *key, GSList **out) } if (start != NULL) - return expand_combo(start, key-1, out); + return expand_combo(start, key-1, out, limit); for (tmp = *out; tmp != NULL; tmp = tmp->next) { GString *str = tmp->data; @@ -346,12 +364,13 @@ static int expand_key(const char *key, GSList **out) static void key_states_scan_key(const char *key, KEY_REC *rec) { GSList *tmp, *out; + int limit = MAX_EXPAND_RECURSION; if (g_strcmp0(rec->info->id, "key") == 0) return; out = g_slist_append(NULL, g_string_new(NULL)); - if (expand_key(key, &out)) { + if (expand_key(key, &out, &limit)) { for (tmp = out; tmp != NULL; tmp = tmp->next) { GString *str = tmp->data; From bf36f71b99b18401dbc6105509b0285146b37286 Mon Sep 17 00:00:00 2001 From: dequis Date: Tue, 22 Sep 2015 00:01:04 -0300 Subject: [PATCH 0137/1650] Fix #291, "/msg +#channel incorrectly shows up as Nick:@#channel" Just passing the full target to the "message irc op_public" signal handler and letting it do the cleanup. The fe_channel_skip_prefix() call in event_privmsg() is kept because recode_in() needs a real channel name, but There was similar code in sig_message_own_wall(), but that one is correct - the /wall command always sends NOTICE @#chan, so I added a comment down there to make it clear. --- src/fe-common/irc/fe-events.c | 10 ++++++---- src/fe-common/irc/fe-irc-messages.c | 22 +++++++++++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c index 3a01b9eb..850174c5 100644 --- a/src/fe-common/irc/fe-events.c +++ b/src/fe-common/irc/fe-events.c @@ -56,11 +56,13 @@ static void event_privmsg(IRC_SERVER_REC *server, const char *data, if (fe_channel_is_opchannel(server, target)) { /* Hybrid 6 feature, send msg to all ops in channel */ - target = (char *)fe_channel_skip_prefix(server, target); - recoded = recode_in(SERVER(server), msg, target); + const char *cleantarget = fe_channel_skip_prefix(server, target); + recoded = recode_in(SERVER(server), msg, cleantarget); + + /* pass the original target to the signal, with the @+ here + * the other one is only needed for recode_in*/ signal_emit("message irc op_public", 5, - server, recoded, nick, addr, - get_visible_target(server, target)); + server, recoded, nick, addr, target); } else { recoded = recode_in(SERVER(server), msg, server_ischannel(SERVER(server), target) ? target : nick); signal_emit(server_ischannel(SERVER(server), target) ? diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index 11d158af..110fb29a 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -37,6 +37,7 @@ #include "fe-queries.h" #include "window-items.h" #include "fe-irc-channels.h" +#include "fe-irc-server.h" static void sig_message_own_public(SERVER_REC *server, const char *msg, const char *target, const char *origtarget) @@ -70,18 +71,28 @@ static void sig_message_irc_op_public(SERVER_REC *server, const char *msg, const char *nick, const char *address, const char *target) { - char *nickmode, *optarget; + char *nickmode, *optarget, *prefix; + const char *cleantarget; + + /* only skip here so the difference can be stored in prefix */ + cleantarget = fe_channel_skip_prefix(IRC_SERVER(server), target); + prefix = g_strndup(target, cleantarget - target); + + /* and clean the rest here */ + cleantarget = get_visible_target(IRC_SERVER(server), cleantarget); nickmode = channel_get_nickmode(channel_find(server, target), nick); - optarget = g_strconcat("@", target, NULL); - printformat_module("fe-common/core", server, target, + optarget = g_strconcat(prefix, cleantarget, NULL); + + printformat_module("fe-common/core", server, cleantarget, MSGLEVEL_PUBLIC, TXT_PUBMSG_CHANNEL, nick, optarget, msg, nickmode); g_free(nickmode); - g_free(optarget); + g_free(optarget); + g_free(prefix); } static void sig_message_own_wall(SERVER_REC *server, const char *msg, @@ -92,7 +103,8 @@ static void sig_message_own_wall(SERVER_REC *server, const char *msg, nickmode = channel_get_nickmode(channel_find(server, target), server->nick); - optarget = g_strconcat("@", target, NULL); + /* this is always @, skip_prefix is not needed here */ + optarget = g_strconcat("@", target, NULL); printformat_module("fe-common/core", server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT, From 99f074b0db2d723c3a1ddbdc5226f54f24b01989 Mon Sep 17 00:00:00 2001 From: dequis Date: Tue, 22 Sep 2015 01:17:15 -0300 Subject: [PATCH 0138/1650] fe_channel_skip_prefix: fix return value (FALSE/NULL isn't valid) The return value is a char*, and here it was false which is 0 which is more or less the same as null. That could have been a crash somewhere, the functions that call this don't expect null ever. --- src/fe-common/irc/fe-irc-channels.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fe-common/irc/fe-irc-channels.c b/src/fe-common/irc/fe-irc-channels.c index d5f17bd0..a2737fc3 100644 --- a/src/fe-common/irc/fe-irc-channels.c +++ b/src/fe-common/irc/fe-irc-channels.c @@ -56,7 +56,7 @@ const char *fe_channel_skip_prefix(IRC_SERVER_REC *server, const char *target) /* Exit early if target doesn't name a channel */ if (server_ischannel(SERVER(server), target) == FALSE) - return FALSE; + return target; statusmsg = g_hash_table_lookup(server->isupport, "statusmsg"); From f5f3d7cc98f24799f562e8d3126ea1c2786a6547 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 22 Sep 2015 21:59:17 +0200 Subject: [PATCH 0139/1650] Revert "Network and IPv{4,6} related changes" --- docs/help/in/toggle.in | 2 +- docs/manual.txt | 3 ++ src/core/chat-commands.c | 6 +-- src/core/chatnet-rec.h | 2 +- src/core/net-nonblock.c | 38 +++++++++---- src/core/net-nonblock.h | 4 +- src/core/network.c | 98 ++++++++++++++++++++++++++++------ src/core/network.h | 2 +- src/core/server-connect-rec.h | 2 +- src/core/server-setup-rec.h | 2 +- src/core/servers-reconnect.c | 10 ++-- src/core/servers-setup.c | 67 ++++++++++++++++------- src/core/servers-setup.h | 2 +- src/core/servers.c | 67 ++++++++++++++++------- src/core/servers.h | 3 +- src/fe-common/core/fe-server.c | 4 +- src/fe-common/irc/fe-ircnet.c | 4 +- src/irc/dcc/dcc.c | 4 +- src/irc/proxy/listen.c | 9 ++-- 19 files changed, 241 insertions(+), 88 deletions(-) diff --git a/docs/help/in/toggle.in b/docs/help/in/toggle.in index 71f5c8f4..f87a6462 100644 --- a/docs/help/in/toggle.in +++ b/docs/help/in/toggle.in @@ -15,7 +15,7 @@ %9Examples:%9 - /TOGGLE resolve_reverse_lookup + /TOGGLE resolve_prefer_ipv6 /TOGGLE channels_rejoin_unavailable ON %9See also:%9 SET diff --git a/docs/manual.txt b/docs/manual.txt index 12d8031e..b2d0de14 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -429,6 +429,9 @@ After connected to server, Irssi can automatically change your user mode. You can set it with /SET usermode , default is +i. + /SET resolve_prefer_ipv6 - If ON, prefer IPv6 for hosts that + have both v4 and v6 addresses. + 5.5 Automatic reconnecting If you get disconnected from server, Irssi will try to reconnect diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index 9c28a1fc..8e881679 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -128,10 +128,10 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, host = g_hash_table_lookup(optlist, "host"); if (host != NULL && *host != '\0') { - IPADDR ip; + IPADDR ip4, ip6; - if (net_gethostbyname(host, &ip) == 0) - server_connect_own_ip_save(conn, &ip); + if (net_gethostbyname(host, &ip4, &ip6) == 0) + server_connect_own_ip_save(conn, &ip4, &ip6); } cmd_params_free(free_arg); diff --git a/src/core/chatnet-rec.h b/src/core/chatnet-rec.h index 3044643a..e3ed8aa0 100644 --- a/src/core/chatnet-rec.h +++ b/src/core/chatnet-rec.h @@ -9,4 +9,4 @@ char *realname; char *own_host; /* address to use when connecting this server */ char *autosendcmd; /* command to send after connecting to this ircnet */ -IPADDR *own_ip; /* resolved own_address if not NULL */ +IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */ diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c index bc8c4b96..e637e673 100644 --- a/src/core/net-nonblock.c +++ b/src/core/net-nonblock.c @@ -103,12 +103,15 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, srand(time(NULL)); memset(&rec, 0, sizeof(rec)); - rec.error = net_gethostbyname(addr, &rec.ip); + rec.error = net_gethostbyname(addr, &rec.ip4, &rec.ip6); if (rec.error == 0) { errorstr = NULL; if (reverse_lookup) { /* reverse lookup the IP, ignore any error */ - net_gethostbyaddr(&rec.ip, &rec.host); + if (rec.ip4.family != 0) + net_gethostbyaddr(&rec.ip4, &rec.host4); + if (rec.ip6.family != 0) + net_gethostbyaddr(&rec.ip6, &rec.host6); } } else { errorstr = net_gethosterror(rec.error); @@ -119,11 +122,18 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, if (rec.errlen != 0) g_io_channel_write_block(pipe, (void *) errorstr, rec.errlen); else { - if (rec.host) { - len = strlen(rec.host) + 1; + if (rec.host4) { + len = strlen(rec.host4) + 1; g_io_channel_write_block(pipe, (void *) &len, sizeof(int)); - g_io_channel_write_block(pipe, (void *) rec.host, + g_io_channel_write_block(pipe, (void *) rec.host4, + len); + } + if (rec.host6) { + len = strlen(rec.host6) + 1; + g_io_channel_write_block(pipe, (void *) &len, + sizeof(int)); + g_io_channel_write_block(pipe, (void *) rec.host6, len); } } @@ -144,7 +154,8 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec) rec->error = -1; rec->errorstr = NULL; - rec->host = NULL; + rec->host4 = NULL; + rec->host6 = NULL; #ifndef WIN32 fcntl(g_io_channel_unix_get_fd(pipe), F_SETFL, O_NONBLOCK); @@ -163,10 +174,15 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec) rec->errorstr = g_malloc0(rec->errlen+1); g_io_channel_read_block(pipe, rec->errorstr, rec->errlen); } else { - if (rec->host) { + if (rec->host4) { g_io_channel_read_block(pipe, &len, sizeof(int)); - rec->host = g_malloc0(len); - g_io_channel_read_block(pipe, rec->host, len); + rec->host4 = g_malloc0(len); + g_io_channel_read_block(pipe, rec->host4, len); + } + if (rec->host6) { + g_io_channel_read_block(pipe, &len, sizeof(int)); + rec->host6 = g_malloc0(len); + g_io_channel_read_block(pipe, rec->host6, len); } } @@ -211,6 +227,7 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe) { RESOLVED_IP_REC iprec; GIOChannel *handle; + IPADDR *ip; g_return_if_fail(rec != NULL); @@ -224,8 +241,9 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe) g_io_channel_shutdown(rec->pipes[1], TRUE, NULL); g_io_channel_unref(rec->pipes[1]); + ip = iprec.ip4.family != 0 ? &iprec.ip4 : &iprec.ip6; handle = iprec.error == -1 ? NULL : - net_connect_ip(&iprec.ip, rec->port, rec->my_ip); + net_connect_ip(ip, rec->port, rec->my_ip); g_free_not_null(rec->my_ip); diff --git a/src/core/net-nonblock.h b/src/core/net-nonblock.h index 581536b3..af5968c8 100644 --- a/src/core/net-nonblock.h +++ b/src/core/net-nonblock.h @@ -4,12 +4,12 @@ #include "network.h" typedef struct { - IPADDR ip; /* resolved ip address */ + IPADDR ip4, ip6; /* resolved ip addresses */ int error; /* error, 0 = no error, -1 = error: */ int errlen; /* error text length */ char *errorstr; /* error string - dynamically allocated, you'll need to free() it yourself unless it's NULL */ - char *host; /* dito */ + char *host4, *host6; /* dito */ } RESOLVED_IP_REC; typedef struct { diff --git a/src/core/network.c b/src/core/network.c index 303483c6..bfaa47fb 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -137,14 +137,35 @@ static int sin_get_port(union sockaddr_union *so) /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) { - IPADDR ip; + IPADDR ip4, ip6, *ip; g_return_val_if_fail(addr != NULL, NULL); - if (net_gethostbyname(addr, &ip) == -1) + if (net_gethostbyname(addr, &ip4, &ip6) == -1) return NULL; - return net_connect_ip(&ip, port, my_ip); + if (my_ip == NULL) { + /* prefer IPv4 addresses */ + ip = ip4.family != 0 ? &ip4 : &ip6; + } else if (IPADDR_IS_V6(my_ip)) { + /* my_ip is IPv6 address, use it if possible */ + if (ip6.family != 0) + ip = &ip6; + else { + my_ip = NULL; + ip = &ip4; + } + } else { + /* my_ip is IPv4 address, use it if possible */ + if (ip4.family != 0) + ip = &ip4; + else { + my_ip = NULL; + ip = &ip6; + } + } + + return net_connect_ip(ip, port, my_ip); } /* Connect to socket with ip address */ @@ -392,35 +413,82 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port) /* Get IP addresses for host, both IPv4 and IPv6 if possible. If ip->family is 0, the address wasn't found. Returns 0 = ok, others = error code for net_gethosterror() */ -int net_gethostbyname(const char *addr, IPADDR *ip) +int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) { +#ifdef HAVE_IPV6 union sockaddr_union *so; - struct addrinfo hints, *ailist; - int ret; + 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(ip, 0, sizeof(IPADDR)); + memset(ip4, 0, sizeof(IPADDR)); + memset(ip6, 0, sizeof(IPADDR)); +#ifdef HAVE_IPV6 memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; -#ifdef HAVE_IPV6 - hints.ai_family = AF_UNSPEC; -#else - hints.ai_family = AF_INET; -#endif - hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG); /* save error to host_error for later use */ ret = getaddrinfo(addr, NULL, &hints, &ailist); if (ret != 0) return ret; - so = (const union sockaddr_union *)ailist->ai_addr; - sin_get_ip(so, ip); + /* count IPs */ + count_v4 = count_v6 = 0; + for (ai = ailist; ai != NULL; ai = ai->ai_next) { + if (ai->ai_family == AF_INET) + count_v4++; + else if (ai->ai_family == AF_INET6) + count_v6++; + } + + if (count_v4 == 0 && count_v6 == 0) + return HOST_NOT_FOUND; /* shouldn't happen? */ + + /* if there are multiple addresses, return random one */ + use_v4 = count_v4 <= 1 ? 0 : rand() % count_v4; + use_v6 = count_v6 <= 1 ? 0 : rand() % count_v6; + + count_v4 = count_v6 = 0; + for (ai = ailist; ai != NULL; ai = ai->ai_next) { + so = (union sockaddr_union *) ai->ai_addr; + + if (ai->ai_family == AF_INET) { + if (use_v4 == count_v4) + sin_get_ip(so, ip4); + count_v4++; + } else if (ai->ai_family == AF_INET6) { + if (use_v6 == count_v6) + sin_get_ip(so, ip6); + count_v6++; + } + } 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. diff --git a/src/core/network.h b/src/core/network.h index ea8b3055..fa7e9675 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -71,7 +71,7 @@ int net_transmit(GIOChannel *handle, const char *data, int len); /* Get IP addresses for host, both IPv4 and IPv6 if possible. If ip->family is 0, the address wasn't found. Returns 0 = ok, others = error code for net_gethosterror() */ -int net_gethostbyname(const char *addr, IPADDR *ip); +int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6); /* 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); diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h index 3f24e7d8..80c5761b 100644 --- a/src/core/server-connect-rec.h +++ b/src/core/server-connect-rec.h @@ -16,7 +16,7 @@ char *address; int port; char *chatnet; -IPADDR *own_ip; +IPADDR *own_ip4, *own_ip6; char *password; char *nick; diff --git a/src/core/server-setup-rec.h b/src/core/server-setup-rec.h index fbf49b2c..2c9614c7 100644 --- a/src/core/server-setup-rec.h +++ b/src/core/server-setup-rec.h @@ -19,7 +19,7 @@ char *ssl_capath; char *ssl_ciphers; char *own_host; /* address to use when connecting this server */ -IPADDR *own_ip; /* resolved own_address if not NULL */ +IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */ time_t last_connect; /* to avoid reconnecting too fast.. */ diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index 3ba18ad0..ae97ecd2 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -177,9 +177,13 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info) dest->username = g_strdup(src->username); dest->realname = g_strdup(src->realname); - if (src->own_ip != NULL) { - dest->own_ip = g_new(IPADDR, 1); - memcpy(dest->own_ip, src->own_ip, sizeof(IPADDR)); + if (src->own_ip4 != NULL) { + dest->own_ip4 = g_new(IPADDR, 1); + memcpy(dest->own_ip4, src->own_ip4, sizeof(IPADDR)); + } + if (src->own_ip6 != NULL) { + dest->own_ip6 = g_new(IPADDR, 1); + memcpy(dest->own_ip6, src->own_ip6, sizeof(IPADDR)); } dest->channels = g_strdup(src->channels); diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index e8506f0f..90a447d4 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -33,22 +33,32 @@ GSList *setupservers; static char *old_source_host; int source_host_ok; /* Use source_host_ip .. */ -IPADDR source_host_ip; /* Resolved address */ +IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */ -static void save_ips(IPADDR *ip, IPADDR **save_ip) +static void save_ips(IPADDR *ip4, IPADDR *ip6, + IPADDR **save_ip4, IPADDR **save_ip6) { - if (ip->family == 0) - g_free_and_null(*save_ip); + if (ip4->family == 0) + g_free_and_null(*save_ip4); else { - if (*save_ip == NULL) - *save_ip = g_new(IPADDR, 1); - memcpy(*save_ip, ip, sizeof(IPADDR)); + if (*save_ip4 == NULL) + *save_ip4 = g_new(IPADDR, 1); + memcpy(*save_ip4, ip4, sizeof(IPADDR)); + } + + if (ip6->family == 0) + g_free_and_null(*save_ip6); + else { + if (*save_ip6 == NULL) + *save_ip6 = g_new(IPADDR, 1); + memcpy(*save_ip6, ip6, sizeof(IPADDR)); } } static void get_source_host_ip(void) { const char *hostname; + IPADDR ip4, ip6; if (source_host_ok) return; @@ -56,21 +66,28 @@ static void get_source_host_ip(void) /* FIXME: This will block! */ hostname = settings_get_str("hostname"); source_host_ok = *hostname != '\0' && - net_gethostbyname(hostname, &source_host_ip) == 0; + net_gethostbyname(hostname, &ip4, &ip6) == 0; + + if (source_host_ok) + save_ips(&ip4, &ip6, &source_host_ip4, &source_host_ip6); + else { + g_free_and_null(source_host_ip4); + g_free_and_null(source_host_ip6); + } } static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host, - IPADDR **own_ip) + IPADDR **own_ip4, IPADDR **own_ip6) { - IPADDR ip; + IPADDR ip4, ip6; - if (*own_ip == NULL) { + if (*own_ip4 == NULL && *own_ip6 == NULL) { /* resolve the IP */ - if (net_gethostbyname(own_host, &ip) == 0) - save_ips(&ip, own_ip); + if (net_gethostbyname(own_host, &ip4, &ip6) == 0) + save_ips(&ip4, &ip6, own_ip4, own_ip6); } - server_connect_own_ip_save(conn, *own_ip); + server_connect_own_ip_save(conn, *own_ip4, *own_ip6); } /* Fill information to connection from server setup record */ @@ -81,7 +98,8 @@ void server_setup_fill_reconn(SERVER_CONNECT_REC *conn, g_return_if_fail(IS_SERVER_SETUP(sserver)); if (sserver->own_host != NULL) { - conn_set_ip(conn, sserver->own_host, &sserver->own_ip); + conn_set_ip(conn, sserver->own_host, + &sserver->own_ip4, &sserver->own_ip6); } if (sserver->chatnet != NULL && conn->chatnet == NULL) @@ -121,9 +139,13 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn, } /* source IP */ - if (source_host_ok) { - conn->own_ip = g_new(IPADDR, 1); - memcpy(conn->own_ip, &source_host_ip, sizeof(IPADDR)); + if (source_host_ip4 != NULL) { + conn->own_ip4 = g_new(IPADDR, 1); + memcpy(conn->own_ip4, source_host_ip4, sizeof(IPADDR)); + } + if (source_host_ip6 != NULL) { + conn->own_ip6 = g_new(IPADDR, 1); + memcpy(conn->own_ip6, source_host_ip6, sizeof(IPADDR)); } signal_emit("server setup fill connect", 1, conn); @@ -184,7 +206,8 @@ static void server_setup_fill_chatnet(SERVER_CONNECT_REC *conn, conn->realname = g_strdup(chatnet->realname);; } if (chatnet->own_host != NULL) { - conn_set_ip(conn, chatnet->own_host, &chatnet->own_ip); + conn_set_ip(conn, chatnet->own_host, + &chatnet->own_ip4, &chatnet->own_ip6); } signal_emit("server setup fill chatnet", 2, conn, chatnet); @@ -458,7 +481,8 @@ static void server_setup_destroy(SERVER_SETUP_REC *rec) signal_emit("server setup destroyed", 1, rec); g_free_not_null(rec->own_host); - g_free_not_null(rec->own_ip); + g_free_not_null(rec->own_ip4); + g_free_not_null(rec->own_ip6); g_free_not_null(rec->chatnet); g_free_not_null(rec->password); g_free_not_null(rec->ssl_cert); @@ -532,6 +556,7 @@ void servers_setup_init(void) settings_add_str("proxy", "proxy_password", ""); setupservers = NULL; + source_host_ip4 = source_host_ip6 = NULL; old_source_host = NULL; read_settings(); @@ -542,6 +567,8 @@ void servers_setup_init(void) void servers_setup_deinit(void) { + g_free_not_null(source_host_ip4); + g_free_not_null(source_host_ip6); g_free_not_null(old_source_host); while (setupservers != NULL) diff --git a/src/core/servers-setup.h b/src/core/servers-setup.h index c4878094..f7601a68 100644 --- a/src/core/servers-setup.h +++ b/src/core/servers-setup.h @@ -16,7 +16,7 @@ struct _SERVER_SETUP_REC { extern GSList *setupservers; -extern IPADDR source_host_ip; /* Resolved address */ +extern IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */ extern int source_host_ok; /* Use source_host_ip .. */ /* Fill reconnection specific information to connection diff --git a/src/core/servers.c b/src/core/servers.c index 66060a7f..3342304e 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -218,7 +218,7 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip, return; if (ip != NULL) { - own_ip = server->connrec->own_ip; + own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4; port = server->connrec->proxy != NULL ? server->connrec->proxy_port : server->connrec->port; handle = server->connrec->use_ssl ? @@ -280,15 +280,30 @@ static void server_connect_callback_readpipe(SERVER_REC *server) server->connect_pipe[0] = NULL; server->connect_pipe[1] = NULL; - ip = NULL; - - if (iprec.error == 0) { - // FIXME : REMOVE THIS BEFORE MERGE - if (server->connrec->family) - g_assert(server->connrec->family == iprec.ip.family); - - ip = &iprec.ip; - servername = iprec.host; + /* figure out if we should use IPv4 or v6 address */ + if (iprec.error != 0) { + /* error */ + ip = NULL; + } else if (server->connrec->family == AF_INET) { + /* force IPv4 connection */ + ip = iprec.ip4.family == 0 ? NULL : &iprec.ip4; + servername = iprec.host4; + } else if (server->connrec->family == AF_INET6) { + /* force IPv6 connection */ + ip = iprec.ip6.family == 0 ? NULL : &iprec.ip6; + servername = iprec.host6; + } else { + /* pick the one that was found, or if both do it like + /SET resolve_prefer_ipv6 says. */ + if (iprec.ip4.family == 0 || + (iprec.ip6.family != 0 && + settings_get_bool("resolve_prefer_ipv6"))) { + ip = &iprec.ip6; + servername = iprec.host6; + } else { + ip = &iprec.ip4; + servername = iprec.host4; + } } if (ip != NULL) { @@ -322,7 +337,8 @@ static void server_connect_callback_readpipe(SERVER_REC *server) } g_free(iprec.errorstr); - g_free(iprec.host); + g_free(iprec.host4); + g_free(iprec.host6); } SERVER_REC *server_connect(SERVER_CONNECT_REC *conn) @@ -607,7 +623,8 @@ void server_connect_unref(SERVER_CONNECT_REC *conn) g_free_not_null(conn->address); g_free_not_null(conn->chatnet); - g_free_not_null(conn->own_ip); + g_free_not_null(conn->own_ip4); + g_free_not_null(conn->own_ip6); g_free_not_null(conn->password); g_free_not_null(conn->nick); @@ -637,15 +654,26 @@ void server_change_nick(SERVER_REC *server, const char *nick) } /* Update own IPv4 and IPv6 records */ -void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, IPADDR *ip) +void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, + IPADDR *ip4, IPADDR *ip6) { - if (ip == NULL || ip->family == 0) - g_free_and_null(conn->own_ip); + if (ip4 == NULL || ip4->family == 0) + g_free_and_null(conn->own_ip4); + if (ip6 == NULL || ip6->family == 0) + g_free_and_null(conn->own_ip6); - if (ip != NULL && ip->family != 0) { - if (conn->own_ip == NULL) - conn->own_ip = g_new0(IPADDR, 1); - memcpy(conn->own_ip, ip, sizeof(IPADDR)); + if (ip4 != NULL && ip4->family != 0) { + /* IPv4 address was found */ + if (conn->own_ip4 == NULL) + conn->own_ip4 = g_new0(IPADDR, 1); + memcpy(conn->own_ip4, ip4, sizeof(IPADDR)); + } + + if (ip6 != NULL && ip6->family != 0) { + /* IPv6 address was found */ + if (conn->own_ip6 == NULL) + conn->own_ip6 = g_new0(IPADDR, 1); + memcpy(conn->own_ip6, ip6, sizeof(IPADDR)); } } @@ -710,6 +738,7 @@ static void sig_chat_protocol_deinit(CHAT_PROTOCOL_REC *proto) void servers_init(void) { + settings_add_bool("server", "resolve_prefer_ipv6", FALSE); settings_add_bool("server", "resolve_reverse_lookup", FALSE); lookup_servers = servers = NULL; diff --git a/src/core/servers.h b/src/core/servers.h index 314faa32..f39c650b 100644 --- a/src/core/servers.h +++ b/src/core/servers.h @@ -67,7 +67,8 @@ void server_connect_failed(SERVER_REC *server, const char *msg); void server_change_nick(SERVER_REC *server, const char *nick); /* Update own IPv4 and IPv6 records */ -void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, IPADDR *ip); +void server_connect_own_ip_save(SERVER_CONNECT_REC *conn, + IPADDR *ip4, IPADDR *ip6); /* `optlist' should contain only one unknown key - the server tag. returns NULL if there was unknown -option */ diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index f8558ad1..429e6dac 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(const char *data) if (*password != '\0') g_free_and_null(rec->password); if (g_hash_table_lookup(optlist, "host")) { g_free_and_null(rec->own_host); - rec->own_ip = NULL; + rec->own_ip4 = rec->own_ip6 = NULL; } } @@ -193,7 +193,7 @@ static void cmd_server_add(const char *data) value = g_hash_table_lookup(optlist, "host"); if (value != NULL && *value != '\0') { rec->own_host = g_strdup(value); - rec->own_ip = NULL; + rec->own_ip4 = rec->own_ip6 = NULL; } signal_emit("server add fill", 2, rec, optlist); diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index 4071f367..6618edd7 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -108,7 +108,7 @@ static void cmd_network_add(const char *data) if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname); if (g_hash_table_lookup(optlist, "host")) { g_free_and_null(rec->own_host); - rec->own_ip = NULL; + rec->own_ip4 = rec->own_ip6 = NULL; } if (g_hash_table_lookup(optlist, "usermode")) g_free_and_null(rec->usermode); if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd); @@ -140,7 +140,7 @@ static void cmd_network_add(const char *data) value = g_hash_table_lookup(optlist, "host"); if (value != NULL && *value != '\0') { rec->own_host = g_strdup(value); - rec->own_ip = NULL; + rec->own_ip4 = rec->own_ip6 = NULL; } value = g_hash_table_lookup(optlist, "usermode"); diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index 7fef2ae5..17f6c477 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -264,12 +264,12 @@ GIOChannel *dcc_connect_ip(IPADDR *ip, int port) } if (own_ip == NULL) - own_ip = &source_host_ip; + own_ip = IPADDR_IS_V6(ip) ? source_host_ip6 : source_host_ip4; handle = net_connect_ip(ip, port, own_ip); if (handle == NULL && errno == EADDRNOTAVAIL && own_ip != NULL) { /* dcc_own_ip is external address */ - own_ip = &source_host_ip; + own_ip = IPADDR_IS_V6(ip) ? source_host_ip6 : source_host_ip4; handle = net_connect_ip(ip, port, own_ip); } return handle; diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c index 16950c79..dcc94e6b 100644 --- a/src/irc/proxy/listen.c +++ b/src/irc/proxy/listen.c @@ -585,7 +585,7 @@ static LISTEN_REC *find_listen(const char *ircnet, int port) static void add_listen(const char *ircnet, int port) { LISTEN_REC *rec; - IPADDR ip, *my_ip; + IPADDR ip4, ip6, *my_ip; if (port <= 0 || *ircnet == '\0') return; @@ -593,13 +593,16 @@ static void add_listen(const char *ircnet, int port) /* bind to specific host/ip? */ my_ip = NULL; if (*settings_get_str("irssiproxy_bind") != '\0') { - if (net_gethostbyname(settings_get_str("irssiproxy_bind"), &ip) != 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 = &ip; + + my_ip = ip6.family == 0 ? &ip4 : ip4.family == 0 || + settings_get_bool("resolve_prefer_ipv6") ? &ip6 : &ip4; } rec = g_new0(LISTEN_REC, 1); From 5a4be0f4f5f36787e98215d87b88a50a5f7e7e01 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Tue, 22 Sep 2015 22:39:44 +0200 Subject: [PATCH 0140/1650] Add new setting to optionally modify behaviour of hilight_nick_matches Fix indentation Remove unused variables that crept into the nick_match_msg_everywhere function --- src/core/nicklist.c | 9 +++++++++ src/core/nicklist.h | 1 + src/fe-common/core/fe-messages.c | 5 ++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/core/nicklist.c b/src/core/nicklist.c index a96b8a9e..c88f5d6d 100644 --- a/src/core/nicklist.c +++ b/src/core/nicklist.c @@ -21,6 +21,7 @@ #include "module.h" #include "signals.h" #include "misc.h" +#include "settings.h" #include "servers.h" #include "channels.h" @@ -571,6 +572,14 @@ int nick_match_msg(CHANNEL_REC *channel, const char *msg, const char *nick) } } +int nick_match_msg_everywhere(CHANNEL_REC *channel, const char *msg, const char *nick) +{ + g_return_val_if_fail(nick != NULL, FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + return stristr_full(msg, nick); +} + void nicklist_init(void) { signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created); diff --git a/src/core/nicklist.h b/src/core/nicklist.h index 55dfd5ef..5e0f4f75 100644 --- a/src/core/nicklist.h +++ b/src/core/nicklist.h @@ -55,6 +55,7 @@ int nicklist_compare(NICK_REC *p1, NICK_REC *p2, const char *nick_prefix); /* Check is `msg' is meant for `nick'. */ int nick_match_msg(CHANNEL_REC *channel, const char *msg, const char *nick); +int nick_match_msg_everywhere(CHANNEL_REC *channel, const char *msg, const char *nick); void nicklist_init(void); void nicklist_deinit(void); diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index 3bd2b666..d09c1b0b 100644 --- a/src/fe-common/core/fe-messages.c +++ b/src/fe-common/core/fe-messages.c @@ -183,7 +183,9 @@ static void sig_message_public(SERVER_REC *server, const char *msg, nickrec = nicklist_find(chanrec, nick); for_me = !settings_get_bool("hilight_nick_matches") ? FALSE : - nick_match_msg(chanrec, msg, server->nick); + !settings_get_bool("hilight_nick_matches_everywhere") ? + nick_match_msg(chanrec, msg, server->nick) : + nick_match_msg_everywhere(chanrec, msg, server->nick); hilight = for_me ? NULL : hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC, msg); color = (hilight == NULL) ? NULL : hilight_get_color(hilight); @@ -694,6 +696,7 @@ void fe_messages_init(void) (GCompareFunc) g_direct_equal); settings_add_bool("lookandfeel", "hilight_nick_matches", TRUE); + settings_add_bool("lookandfeel", "hilight_nick_matches_everywhere", FALSE); settings_add_bool("lookandfeel", "emphasis", TRUE); settings_add_bool("lookandfeel", "emphasis_replace", FALSE); settings_add_bool("lookandfeel", "emphasis_multiword", FALSE); From b5c3e90802e926e35ad9a4f1f02403578a3ff392 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Tue, 22 Sep 2015 23:09:55 +0200 Subject: [PATCH 0141/1650] Fix return value from nick_match_msg_everywhere --- src/core/nicklist.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/nicklist.c b/src/core/nicklist.c index c88f5d6d..160deb6a 100644 --- a/src/core/nicklist.c +++ b/src/core/nicklist.c @@ -577,7 +577,12 @@ int nick_match_msg_everywhere(CHANNEL_REC *channel, const char *msg, const char g_return_val_if_fail(nick != NULL, FALSE); g_return_val_if_fail(msg != NULL, FALSE); - return stristr_full(msg, nick); + char *ret = stristr_full(msg, nick); + + if (ret != NULL) + return TRUE; + + return FALSE; } void nicklist_init(void) From 3f2eaf1d3a67eddd42dd88eccb39402d45297fcb Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Tue, 22 Sep 2015 23:16:41 +0200 Subject: [PATCH 0142/1650] Fix return value from nick_match_msg_everywhere, remove #include 'settings.h' --- src/core/nicklist.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/core/nicklist.c b/src/core/nicklist.c index 160deb6a..770b0afc 100644 --- a/src/core/nicklist.c +++ b/src/core/nicklist.c @@ -21,7 +21,6 @@ #include "module.h" #include "signals.h" #include "misc.h" -#include "settings.h" #include "servers.h" #include "channels.h" @@ -577,12 +576,7 @@ int nick_match_msg_everywhere(CHANNEL_REC *channel, const char *msg, const char g_return_val_if_fail(nick != NULL, FALSE); g_return_val_if_fail(msg != NULL, FALSE); - char *ret = stristr_full(msg, nick); - - if (ret != NULL) - return TRUE; - - return FALSE; + return stristr_full(msg, nick) != NULL; } void nicklist_init(void) From f247a43b97731cd1d58ec765dd2d10f885ef66dc Mon Sep 17 00:00:00 2001 From: dequis Date: Tue, 22 Sep 2015 19:35:10 -0300 Subject: [PATCH 0143/1650] sig_message_irc_op_public: fix nickmode lookup, use cleantarget instead --- src/fe-common/irc/fe-irc-messages.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index 110fb29a..40ca306d 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -81,7 +81,7 @@ static void sig_message_irc_op_public(SERVER_REC *server, const char *msg, /* and clean the rest here */ cleantarget = get_visible_target(IRC_SERVER(server), cleantarget); - nickmode = channel_get_nickmode(channel_find(server, target), + nickmode = channel_get_nickmode(channel_find(server, cleantarget), nick); optarget = g_strconcat(prefix, cleantarget, NULL); From 7ae742293926dde06be5563efb5acd19dc2c3a75 Mon Sep 17 00:00:00 2001 From: dequis Date: Wed, 23 Sep 2015 03:17:29 -0300 Subject: [PATCH 0144/1650] Add multi-prefix to list of capabilities to request Turns out event_names_list() in irc-nicklist.c already handles this. event_who() just ignores it, which is probably a good idea since some of the irc servers I tested this with have a bug that results in sending multiple prefixes in the NAMES reply but not in the WHO one (they were forks of ircd-hybrid before 7.3.0) And NAMES always happens, anyway. WHO is omitted sometimes for huge channels. --- src/irc/core/irc-servers.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 82584382..81f0c269 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -228,6 +228,8 @@ static void server_init(IRC_SERVER_REC *server) if (conn->sasl_mechanism != SASL_MECHANISM_NONE) cap_toggle(server, "sasl", TRUE); + cap_toggle(server, "multi-prefix", TRUE); + irc_send_cmd_now(server, "CAP LS"); if (conn->password != NULL && *conn->password != '\0') { From d3df165e0b067461e49d7f065f3820739e9ba229 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Sun, 12 Jul 2015 19:03:58 +0200 Subject: [PATCH 0145/1650] Improve the WINDOW help Properly describe the window command. Make help sort order deterministic. --- docs/help/in/window.in | 84 +++++++++++++++++++++--------------------- syntax.pl | 2 +- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/docs/help/in/window.in b/docs/help/in/window.in index c965d3fb..6dde6c50 100644 --- a/docs/help/in/window.in +++ b/docs/help/in/window.in @@ -5,49 +5,49 @@ %9Parameters:%9 - LOG: Modifies the logging status. - LOGFILE: Modifies the location to the log file. - NEW: Creates a new window. - CLOSE: Closes a window. - REFNUM: Go to the window with the given number. - GOTO: Go to the window with the given nickname, channel or number. - NEXT: Go to the next window. - LAST: Go to the last window. - PREVIOUS: Go to the previous window. - LEVEL: Modifies the text levels to display in the window. - IMMORTAL: Modifies the window mortality status. - SERVER: Set the active server of the window. - ITEM PREV: Go to the previous item in the window. - ITEM NEXT: Go to the next item in the window. - ITEM GOTO: Go to the specified nickname, channel or window item number. - ITEM MOVE: Move the active window item to another window. - NUMBER: Move the active window to another position. - NAME: Give the window a name. - HISTORY: Clears the window history buffer. - MOVE PREV: Move the window down. - MOVE NEXT: Move the window up. - MOVE FIRST: Move the window to the first position. - MOVE LAST: Move the window to the last position. - MOVE: Move the window. - LIST: List all the windows. - THEME: Applies a theme to the windows. - GROW: Increase the window size when using split windows. - SHRINK: Decrease the window size when using split windows. - SIZE: Modify the window size when using split windows. - BALANCE: Balance the window locations when using split windows. - HIDE: Hide the window when using split windows. - SHOW: Show the window when using split windows. - UP: Go to the window above when using split windows. - DOWN: Go to the window below when using split windows. - LEFT: Go to the previous window. - RIGHT: Go to the next window. - STICK: Make the window sticky. - MOVE LEFT: Move the window to the previous location. - MOVE RIGHT: Move the window to the next location. - MOVE UP: Move the window up when using split windows. - MOVE DOWN: Move the window down when using split windows. + LOG: %|Turn on or off logging of the active window, optionally specifying the log file to use. + LOGFILE: %|Sets the location of the log file to use for window logging without starting to log. + NEW: %|Creates a new hidden or split window. + CLOSE: %|Closes the current window, the specified one or all windows in the given range. + REFNUM: %|Go to the window with the given number. + GOTO: %|Go to the window with activity, with the given nickname, channel or with the specified number. + NEXT: %|Go to the next window numerically. + LAST: %|Go to the previously active window. + PREVIOUS: %|Go to the previous window numerically. + LEVEL: %|Changes the text levels to display in the window, or query the current level. + IMMORTAL: %|Modifies or queries the window mortality status. Immortal windows have an extra protection against WINDOW CLOSE. + SERVER: %|Change the active server of the window or the server stickyness. If the server is sticky, it cannot be cycled with next_window_item/previous_window_item + ITEM PREV: %|Make the previous item in this window active. + ITEM NEXT: %|Make the next item in this window active. + ITEM GOTO: %|Change to the query with the specified nickname, channel with the given name or window item number. + ITEM MOVE: %|Move the active window item to another window, or move the channel or query item specified by their name to the current window. + NUMBER: %|Change the active window number to the specified number, swapping the window already in that place if required. With -sticky, protect the window number from renumbering done by windows_auto_renumber. (To re-set the sticky attribute, use WINDOW NUMBER again without -sticky.) + NAME: %|Change or clear the window name. Window names must be unique. + HISTORY: %|Set or clear a specific named history to use for this window. All windows with the same named history will share a history. + MOVE PREV: %|Move the window to the place of the numerically previous window. At the first position, move the window to the end and renumber the consecutive block that it was part of. + MOVE NEXT: %|Move the window to the place of the numerically next window. At the last position, move the window to the first position and renumber the consecutive block at first position (if any) + MOVE FIRST: %|Move the window to the first position. Any windows inbetween are moved to their numerically next positions. + MOVE LAST: %|Move the window to the last position. Any windows inbetween are moved to their numerically previous positions. + MOVE: %|Move the window to the specified number or the first number that is in use when moving the window in the direction of the specified position. Any windows inbetween are shifted towards the old position of the window (unused positions remain empty) + LIST: %|List all the windows. + THEME: %|Applies or removes a per-window theme. + GROW: %|Increase the size of the active split window by the specified number of lines. + SHRINK: %|Decrease the size of the active split window by the specified number of lines. + SIZE: %|Set the current split window size to the specified numer of lines. + BALANCE: %|Balance the heights of all split windows. + HIDE: %|Hides the current split window, or the split window specified by number or item name. + SHOW: %|Show the window specified by number or item name as a new split windows. It is made sticky when autostick_split_windows is turned on. + UP: %|Set the split window above the current one active. At the top, wraps to the bottom. + DOWN: %|Set the split window below the current one active. At the bottom, wraps to the top. + LEFT: %|Go to the previous window numerically that is part of the current sticky group (or not part of any sticky group). + RIGHT: %|Go to the next window numerically that is part of the current sticky group (or not part of any sticky group). + STICK: %|Make the currently active window sticky, or stick the window specified by number to the currently visible split window. Or turn off stickyness of the currently active window or the window specified by number. + MOVE LEFT: %|Move the window to the numerically previous location inside the current sticky group. + MOVE RIGHT: %|Move the window to the numerically next location inside the current sticky group. + MOVE UP: %|Move the current window to the sticky group of the split window above. If no sticky group remains, the split window collapses. + MOVE DOWN: %|Move the current window to the sticky group of the split window below. If no sticky group remains, the split window collapses. - Add the required arguments for the given command. + %|Add the required arguments for the given command. Without arguments, the details (size, immortality, levels, server, name and sticky group) of the currently active window are displayed. If used with a number as argument, same as WINDOW REFNUM. %9Description:%9 diff --git a/syntax.pl b/syntax.pl index bf10451f..33bd12b4 100755 --- a/syntax.pl +++ b/syntax.pl @@ -10,7 +10,7 @@ # Remember to include the asterisk ('*'). $SRC_PATH='src'; -@files = `find src -name '*.c'`; +@files = sort `find src -name '*.c'`; foreach $file (@files) { open (FILE, "$file"); From c9be1a7a80974858a21fc74191198189030df40b Mon Sep 17 00:00:00 2001 From: dequis Date: Wed, 23 Sep 2015 13:37:14 -0300 Subject: [PATCH 0146/1650] Revert "Revert "Bug fix - docdir is ignored during installation."" This reverts commit d222c11f74a5662df59e00e7ae6c8105179a804e. --- docs/Makefile.am | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index 5e222564..861a2ca4 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,5 +1,3 @@ -docdir = $(datadir)/doc/irssi - man_MANS = \ irssi.1 From e833521cefdedcdbc0e4382715a36ea5f8276a86 Mon Sep 17 00:00:00 2001 From: dequis Date: Wed, 23 Sep 2015 13:39:07 -0300 Subject: [PATCH 0147/1650] Bump glib2 requirement from 2.6 to 2.16 This drops support for rhel/centos 5 (18 months left of its 10 year support cycle) Keeps support for debian 5.0 (lenny) and ubuntu 8.04 LTS, both of which are unsupported, so bumping up to glib 2.24 wouldn't be a problem, but it's not needed atm. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e33b8c1d..7bcd3fe7 100644 --- a/configure.ac +++ b/configure.ac @@ -261,7 +261,7 @@ for try in 1 2; do echo "*** trying without -lgmodule" glib_modules= fi - AM_PATH_GLIB_2_0(2.6.0,,, $glib_modules) + AM_PATH_GLIB_2_0(2.16.0,,, $glib_modules) if test "$GLIB_LIBS"; then if test $glib_modules = gmodule; then AC_DEFINE(HAVE_GMODULE) From 9da445ab86740be13f47da7eb540fb9e4b962085 Mon Sep 17 00:00:00 2001 From: dequis Date: Wed, 23 Sep 2015 13:42:00 -0300 Subject: [PATCH 0148/1650] Drop some glib version checks that are not needed anymore The g_strcmp0 fallback in particular was broken since it was used in a few places as a GCompareFunc, and macros don't work that way. Yes, that one was my fault, but nobody complained :D --- src/common.h | 13 ------------- src/fe-common/core/fe-common-core.c | 11 ----------- 2 files changed, 24 deletions(-) diff --git a/src/common.h b/src/common.h index e9073925..86a079fe 100644 --- a/src/common.h +++ b/src/common.h @@ -43,19 +43,6 @@ # include #endif -#if !GLIB_CHECK_VERSION(2,10,0) -#define g_slice_alloc(size) g_malloc(size) -#define g_slice_alloc0(size) g_malloc0(size) -#define g_slice_free1(size, mem) g_free(mem) -#define g_slice_new(type) g_new(type, 1) -#define g_slice_new0(type) g_new0(type, 1) -#define g_slice_free(type, mem) g_free(mem) -#endif - -#if !GLIB_CHECK_VERSION(2,16,0) -#define g_strcmp0(a, b) (!a ? -(a != b) : (!b ? (a != b) : strcmp(a, b))) -#endif - #if defined (UOFF_T_INT) typedef unsigned int uoff_t; #elif defined (UOFF_T_LONG) diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index 341902df..a15850e2 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -450,18 +450,7 @@ void fe_common_core_finish_init(void) signal_add_first("setup changed", (SIGNAL_FUNC) sig_setup_changed); /* _after_ windows are created.. */ -#if GLIB_CHECK_VERSION(2,6,0) g_log_set_default_handler((GLogFunc) glog_func, NULL); -#else - g_log_set_handler(G_LOG_DOMAIN, - (GLogLevelFlags) (G_LOG_LEVEL_CRITICAL | - G_LOG_LEVEL_WARNING), - (GLogFunc) glog_func, NULL); - g_log_set_handler("GLib", - (GLogLevelFlags) (G_LOG_LEVEL_CRITICAL | - G_LOG_LEVEL_WARNING), - (GLogFunc) glog_func, NULL); /* send glib errors to the same place */ -#endif if (setup_changed) signal_emit("setup changed", 0); From b984f1fa250fd87b2808bed6826f17386ddb30ce Mon Sep 17 00:00:00 2001 From: Robert C Jensen Date: Wed, 23 Sep 2015 23:39:37 -0300 Subject: [PATCH 0149/1650] dcc-get: close() the temp fd so we don't get ETXTBSY in ntfs mounts Patch from debian bug 696963 [1] Fixes github bug #220 and flyspray bug 867 [2] [1]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=696963 [2]: http://bugs.irssi.org/index.php?do=details&task_id=867 --- src/irc/dcc/dcc-get.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c index 1208b5c5..a8b1c967 100644 --- a/src/irc/dcc/dcc-get.c +++ b/src/irc/dcc/dcc-get.c @@ -226,6 +226,8 @@ void sig_dccget_connected(GET_DCC_REC *dcc) else ret = fchmod(temphandle, dcc_file_create_mode); + close(temphandle); + if (ret != -1) { ret = link(tempfname, dcc->file); @@ -249,7 +251,6 @@ void sig_dccget_connected(GET_DCC_REC *dcc) /* close/remove the temp file */ ret_errno = errno; - close(temphandle); unlink(tempfname); g_free(tempfname); From a2277e84bd390b9eaca906541f32e5d60e529f7f Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Thu, 24 Sep 2015 11:59:18 +0200 Subject: [PATCH 0150/1650] Added functionality to create dir if dir specified in rawlog filename --- src/core/rawlog.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/rawlog.c b/src/core/rawlog.c index 2fa6b850..875c0ef2 100644 --- a/src/core/rawlog.c +++ b/src/core/rawlog.c @@ -32,6 +32,7 @@ static int rawlog_lines; static int signal_rawlog; static int log_file_create_mode; +static int log_dir_create_mode; RAWLOG_REC *rawlog_create(void) { @@ -145,9 +146,13 @@ void rawlog_close(RAWLOG_REC *rawlog) void rawlog_save(RAWLOG_REC *rawlog, const char *fname) { - char *path; + char *path, *dir; int f; + dir = g_path_get_dirname(fname); + mkpath(dir, log_dir_create_mode); + g_free(dir); + path = convert_home(fname); f = open(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); g_free(path); @@ -165,6 +170,11 @@ static void read_settings(void) { rawlog_set_size(settings_get_int("rawlog_lines")); log_file_create_mode = octal2dec(settings_get_int("log_create_mode")); + log_dir_create_mode = log_file_create_mode; + if (log_file_create_mode & 0400) log_dir_create_mode |= 0100; + if (log_file_create_mode & 0040) log_dir_create_mode |= 0010; + if (log_file_create_mode & 0004) log_dir_create_mode |= 0001; + } static void cmd_rawlog(const char *data, SERVER_REC *server, void *item) From deb6ca1b1a676fae094253fc55519e2a60c206d1 Mon Sep 17 00:00:00 2001 From: Jari Matilainen Date: Thu, 24 Sep 2015 13:03:02 +0200 Subject: [PATCH 0151/1650] Applied patch from fs#275 to make /hilight -mask -line work properly --- src/fe-common/core/fe-messages.c | 16 ++++++++++------ src/fe-common/core/formats.c | 2 ++ src/fe-common/core/formats.h | 6 ++++++ src/fe-common/core/hilight-text.c | 9 ++++----- src/fe-common/core/hilight-text.h | 2 +- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index d09c1b0b..e06a4571 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; + int match_beg = 0, match_end = 0; /* NOTE: this may return NULL if some channel is just closed with /WINDOW CLOSE and server still sends the few last messages */ @@ -187,8 +188,8 @@ static void sig_message_public(SERVER_REC *server, const char *msg, nick_match_msg(chanrec, msg, server->nick) : nick_match_msg_everywhere(chanrec, msg, server->nick); hilight = for_me ? NULL : - hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC, msg); - color = (hilight == NULL) ? NULL : hilight_get_color(hilight); + hilight_match(server, target, nick, address, MSGLEVEL_PUBLIC, msg, &match_beg, &match_end); + color = (hilight == NULL || !hilight->nick) ? NULL : hilight_get_color(hilight); print_channel = chanrec == NULL || !window_item_is_active((WI_ITEM_REC *) chanrec); @@ -214,10 +215,13 @@ 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.hilight = hilight; + dest.match_beg = match_beg; + dest.match_end = match_end; if (color != NULL) { /* highlighted nick */ - TEXT_DEST_REC dest; - format_create_dest(&dest, server, target, level, NULL); hilight_update_text_dest(&dest,hilight); if (!print_channel) /* message to active channel in window */ printformat_dest(&dest, TXT_PUBMSG_HILIGHT, color, @@ -228,11 +232,11 @@ static void sig_message_public(SERVER_REC *server, const char *msg, nickmode); } else { if (!print_channel) - printformat(server, target, level, + printformat_dest(&dest, for_me ? TXT_PUBMSG_ME : TXT_PUBMSG, printnick, msg, nickmode); else - printformat(server, target, level, + printformat_dest(&dest, for_me ? TXT_PUBMSG_ME_CHANNEL : TXT_PUBMSG_CHANNEL, printnick, target, msg, nickmode); diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index ccf48394..b95b3966 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -416,6 +416,8 @@ void format_create_dest_tag(TEXT_DEST_REC *dest, void *server, dest->server_tag = server != NULL ? SERVER(server)->tag : server_tag; dest->target = target; dest->level = level; + dest->match_beg = 0; + dest->match_end = 0; dest->window = window != NULL ? window : window_find_closest(server, target, level); } diff --git a/src/fe-common/core/formats.h b/src/fe-common/core/formats.h index 07e1832c..484105f9 100644 --- a/src/fe-common/core/formats.h +++ b/src/fe-common/core/formats.h @@ -45,6 +45,9 @@ struct _FORMAT_REC { #define PRINT_FLAG_SET_SERVERTAG 0x0010 #define PRINT_FLAG_UNSET_SERVERTAG 0x0020 +// FIXME: sould use better +typedef struct _HILIGHT_REC HILIGHT_REC; + typedef struct _TEXT_DEST_REC { WINDOW_REC *window; SERVER_REC *server; @@ -52,6 +55,9 @@ typedef struct _TEXT_DEST_REC { const char *target; int level; + HILIGHT_REC *hilight; + int match_beg; + int match_end; int hilight_priority; char *hilight_color; int flags; diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 87c5d467..c6017d2a 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -325,11 +325,10 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text, if (dest->level & MSGLEVEL_NOHILIGHT) return; - hilight_start = hilight_end = 0; - hilight = hilight_match(dest->server, dest->target, - NULL, NULL, dest->level, stripped, - &hilight_start, - &hilight_end); + hilight_start = dest->match_beg; + hilight_end = dest->match_end; + hilight = dest->hilight; + if (hilight == NULL) return; diff --git a/src/fe-common/core/hilight-text.h b/src/fe-common/core/hilight-text.h index 1692b8ab..fa083882 100644 --- a/src/fe-common/core/hilight-text.h +++ b/src/fe-common/core/hilight-text.h @@ -7,7 +7,7 @@ #include "formats.h" -typedef struct _HILIGHT_REC HILIGHT_REC; +//typedef struct _HILIGHT_REC HILIGHT_REC; struct _HILIGHT_REC { char *text; From 1a2c479bc04cdb6758ca9f1976e235b092cc83fb Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 26 Sep 2015 18:53:10 +0200 Subject: [PATCH 0152/1650] Allow the user to set and modify the SASL parameters The /NETWORK ADD command now is able to modify the SASL mechanism, the username and the password on a chatnet basis. --- docs/help/in/network.in | 6 ++++++ src/fe-common/irc/fe-ircnet.c | 24 +++++++++++++++++++----- src/irc/core/irc-chatnets.c | 12 ++++++++---- src/irc/core/irc-servers-setup.c | 2 +- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/docs/help/in/network.in b/docs/help/in/network.in index 046d9feb..2918f6ae 100644 --- a/docs/help/in/network.in +++ b/docs/help/in/network.in @@ -32,6 +32,12 @@ additional commands to the server. -cmdmax: Specifies the maximum number of commands to perform before starting the internal flood protection. + -sasl_mechanism Specifies the mechanism to use for the SASL authentication. + At the moment irssi only supports the 'plain' and the + 'external' mechanisms. + -sasl_username Specifies the username to use during the SASL authentication. + -sasl_password Specifies the password to use during the SASL authentication. + The name of the network to add, edit or remove; if no parameter is given, the list of networks will be displayed. diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index 6618edd7..dab6f57f 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -82,10 +82,12 @@ static void cmd_network_list(void) } /* SYNTAX: NETWORK ADD [-nick ] [-user ] [-realname ] - [-host ] [-usermode ] [-autosendcmd ] - [-querychans ] [-whois ] [-msgs ] - [-kicks ] [-modes ] - [-cmdspeed ] [-cmdmax ] */ + [-host ] [-usermode ] [-autosendcmd ] + [-querychans ] [-whois ] [-msgs ] + [-kicks ] [-modes ] [-cmdspeed ] + [-cmdmax ] [-sasl_mechanism ] + [-sasl_username ] [-sasl_password ] + */ static void cmd_network_add(const char *data) { GHashTable *optlist; @@ -112,6 +114,9 @@ static void cmd_network_add(const char *data) } if (g_hash_table_lookup(optlist, "usermode")) g_free_and_null(rec->usermode); if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd); + if (g_hash_table_lookup(optlist, "sasl_mechanism")) g_free_and_null(rec->sasl_mechanism); + if (g_hash_table_lookup(optlist, "sasl_username")) g_free_and_null(rec->sasl_username); + if (g_hash_table_lookup(optlist, "sasl_password")) g_free_and_null(rec->sasl_password); } value = g_hash_table_lookup(optlist, "kicks"); @@ -148,6 +153,14 @@ static void cmd_network_add(const char *data) value = g_hash_table_lookup(optlist, "autosendcmd"); if (value != NULL && *value != '\0') rec->autosendcmd = g_strdup(value); + /* the validity of the parameters is checked in sig_server_setup_fill_chatnet */ + value = g_hash_table_lookup(optlist, "sasl_mechanism"); + if (value != NULL && *value != '\0') rec->sasl_mechanism = g_strdup(value); + value = g_hash_table_lookup(optlist, "sasl_username"); + if (value != NULL && *value != '\0') rec->sasl_username = g_strdup(value); + value = g_hash_table_lookup(optlist, "sasl_password"); + if (value != NULL && *value != '\0') rec->sasl_password = g_strdup(value); + ircnet_create(rec); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NETWORK_ADDED, name); @@ -186,7 +199,8 @@ void fe_ircnet_init(void) command_bind("network add", NULL, (SIGNAL_FUNC) cmd_network_add); command_bind("network remove", NULL, (SIGNAL_FUNC) cmd_network_remove); - command_set_options("network add", "-kicks -msgs -modes -whois -cmdspeed -cmdmax -nick -user -realname -host -autosendcmd -querychans -usermode"); + command_set_options("network add", "-kicks -msgs -modes -whois -cmdspeed " + "-cmdmax -nick -user -realname -host -autosendcmd -querychans -usermode -sasl_mechanism -sasl_username -sasl_password"); } void fe_ircnet_deinit(void) diff --git a/src/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c index b9b221b8..d72f71dd 100644 --- a/src/irc/core/irc-chatnets.c +++ b/src/irc/core/irc-chatnets.c @@ -49,9 +49,9 @@ static void sig_chatnet_read(IRC_CHATNET_REC *rec, CONFIG_NODE *node) rec->max_modes = config_node_get_int(node, "max_modes", 0); rec->max_whois = config_node_get_int(node, "max_whois", 0); - rec->sasl_mechanism = config_node_get_str(node, "sasl_mechanism", NULL); - rec->sasl_username = config_node_get_str(node, "sasl_username", NULL); - rec->sasl_password = config_node_get_str(node, "sasl_password", NULL); + rec->sasl_mechanism = g_strdup(config_node_get_str(node, "sasl_mechanism", NULL)); + rec->sasl_username = g_strdup(config_node_get_str(node, "sasl_username", NULL)); + rec->sasl_password = g_strdup(config_node_get_str(node, "sasl_password", NULL)); } static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node) @@ -88,8 +88,12 @@ static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node) static void sig_chatnet_destroyed(IRC_CHATNET_REC *rec) { - if (IS_IRC_CHATNET(rec)) + if (IS_IRC_CHATNET(rec)) { g_free(rec->usermode); + g_free(rec->sasl_mechanism); + g_free(rec->sasl_username); + g_free(rec->sasl_password); + } } diff --git a/src/irc/core/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c index f5e4f8f4..bf1d2ddf 100644 --- a/src/irc/core/irc-servers-setup.c +++ b/src/irc/core/irc-servers-setup.c @@ -81,7 +81,7 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn, if (ircnet->max_query_chans > 0) conn->max_query_chans = ircnet->max_query_chans; - /* Validate the SASL parameters filled by sig_chatnet_read() */ + /* Validate the SASL parameters filled by sig_chatnet_read() or cmd_network_add */ conn->sasl_mechanism = SASL_MECHANISM_NONE; if (ircnet->sasl_mechanism != NULL) { From 6f9fc5d5230f6d094130bd4f0ce659b740ed2a54 Mon Sep 17 00:00:00 2001 From: dequis Date: Sun, 27 Sep 2015 02:15:14 -0300 Subject: [PATCH 0153/1650] INSTALL: mention local::lib for home directory installations I had problems installing this and this file didn't have the answer. So I'm adding what nei told me to do. --- INSTALL | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/INSTALL b/INSTALL index 719369de..a83a6c76 100644 --- a/INSTALL +++ b/INSTALL @@ -94,6 +94,10 @@ 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. You can verify that the perl module is loaded and working with "/LOAD" command. It should print something like: From 72ac27e5a030b7c9207ecd00b8c2d092d28da644 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 8 Sep 2015 00:40:25 +0200 Subject: [PATCH 0154/1650] Implement the bracketed paste mode As an alternative method of paste detection, more reliable but might not be supported by all the VTs. --- src/fe-text/gui-readline.c | 42 +++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index ec61e317..b8f3c1c7 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -37,6 +37,7 @@ #include "gui-windows.h" #include "utf8.h" +#include #include typedef void (*ENTRY_REDIRECT_KEY_FUNC) (int key, void *data, SERVER_REC *server, WI_ITEM_REC *item); @@ -65,6 +66,13 @@ static char *paste_old_prompt; static int paste_prompt, paste_line_count; static int paste_join_multiline; static int paste_timeout_id; +static int paste_bracketed_mode; + +/* Terminal sequences that surround the input when the terminal has the + * bracketed paste mode active. Fror more details see + * https://cirw.in/blog/bracketed-paste */ +static const unichar bp_start[] = { 0x1b, '[', '2', '0', '0', '~' }; +static const unichar bp_end[] = { 0x1b, '[', '2', '0', '1', '~' }; static void sig_input(void); @@ -647,12 +655,43 @@ static void sig_input(void) unichar key; term_gets(buffer, &line_count); key = g_array_index(buffer, unichar, 0); + /* Either Ctrl-k or Ctrl-c is pressed */ if (key == 11 || key == 3) paste_flush(key == 11); g_array_free(buffer, TRUE); } else { term_gets(paste_buffer, &paste_line_count); - if (paste_detect_time > 0 && paste_buffer->len >= 3) { + + /* use the bracketed paste mode to detect when the user has + * pasted some text into the field. */ + if (paste_buffer->len > 12) { + /* try to find the start/end sequence */ + int seq_start = memmem(paste_buffer->data, + paste_buffer->len * g_array_get_element_size(paste_buffer), + bp_start, sizeof(bp_start)) != NULL, + seq_end = memmem(paste_buffer->data, + paste_buffer->len * g_array_get_element_size(paste_buffer), + bp_end, sizeof(bp_end)) != NULL; + + g_warning("found sequences : start %d end %d", seq_start, seq_end); + + if (seq_start) { + paste_bracketed_mode = TRUE; + /* remove the leading sequence chars */ + memmove(paste_buffer->data, paste_buffer->data + sizeof(bp_start), + paste_buffer->len * g_array_get_element_size(paste_buffer) - sizeof(bp_start)); + g_array_set_size(paste_buffer, paste_buffer->len - 6); + } + + if (seq_end) { + paste_bracketed_mode = FALSE; + /* remove the trailing sequence chars */ + g_array_set_size(paste_buffer, paste_buffer->len - 6); + /* decide what to do with the buffer */ + paste_timeout(NULL); + } + } + else if (paste_detect_time > 0 && paste_buffer->len >= 3) { if (paste_timeout_id != -1) g_source_remove(paste_timeout_id); paste_timeout_id = g_timeout_add(paste_detect_time, paste_timeout, NULL); @@ -945,6 +984,7 @@ void gui_readline_init(void) paste_buffer = g_array_new(FALSE, FALSE, sizeof(unichar)); paste_old_prompt = NULL; paste_timeout_id = -1; + paste_bracketed_mode = FALSE; g_get_current_time(&last_keypress); input_listen_init(STDIN_FILENO); From f1eead7b4a7cdcae6d71dba6e97d38e9d34fcf95 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 8 Sep 2015 00:48:13 +0200 Subject: [PATCH 0155/1650] Toggles --- src/fe-text/gui-readline.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index b8f3c1c7..90399711 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -66,6 +66,7 @@ static char *paste_old_prompt; static int paste_prompt, paste_line_count; static int paste_join_multiline; static int paste_timeout_id; +static int paste_use_bracketed_mode; static int paste_bracketed_mode; /* Terminal sequences that surround the input when the terminal has the @@ -662,11 +663,11 @@ static void sig_input(void) } else { term_gets(paste_buffer, &paste_line_count); - /* use the bracketed paste mode to detect when the user has - * pasted some text into the field. */ - if (paste_buffer->len > 12) { + /* use the bracketed paste mode to detect when the user pastes + * some text into the entry */ + if (paste_use_bracketed_mode != FALSE && paste_buffer->len > 12) { /* try to find the start/end sequence */ - int seq_start = memmem(paste_buffer->data, + int seq_start = memmem(paste_buffer->data, paste_buffer->len * g_array_get_element_size(paste_buffer), bp_start, sizeof(bp_start)) != NULL, seq_end = memmem(paste_buffer->data, @@ -678,7 +679,7 @@ static void sig_input(void) if (seq_start) { paste_bracketed_mode = TRUE; /* remove the leading sequence chars */ - memmove(paste_buffer->data, paste_buffer->data + sizeof(bp_start), + memmove(paste_buffer->data, paste_buffer->data + sizeof(bp_start), paste_buffer->len * g_array_get_element_size(paste_buffer) - sizeof(bp_start)); g_array_set_size(paste_buffer, paste_buffer->len - 6); } @@ -969,6 +970,7 @@ static void setup_changed(void) paste_verify_line_count = settings_get_int("paste_verify_line_count"); paste_join_multiline = settings_get_bool("paste_join_multiline"); + paste_use_bracketed_mode = settings_get_bool("paste_use_bracketed_mode"); } void gui_readline_init(void) @@ -990,6 +992,7 @@ void gui_readline_init(void) 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); /* NOTE: function keys can generate at least 5 characters long keycodes. this must be larger to allow them to work. */ settings_add_int("misc", "paste_verify_line_count", 5); From 15dad291c7829c4ae7855880654b94d6edb4f17f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 8 Sep 2015 00:55:34 +0200 Subject: [PATCH 0156/1650] Replace some hairy logic with g_array_remove_range In the hope it'll do the same under the hood. --- src/fe-text/gui-readline.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 90399711..c4c0064e 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -679,9 +679,7 @@ static void sig_input(void) if (seq_start) { paste_bracketed_mode = TRUE; /* remove the leading sequence chars */ - memmove(paste_buffer->data, paste_buffer->data + sizeof(bp_start), - paste_buffer->len * g_array_get_element_size(paste_buffer) - sizeof(bp_start)); - g_array_set_size(paste_buffer, paste_buffer->len - 6); + g_array_remove_range(paste_buffer, 0, 6); } if (seq_end) { From 4764b102ff274f4a8695ced2ff2ebb39bf8d7bc2 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 9 Sep 2015 22:35:11 +0200 Subject: [PATCH 0157/1650] Enable the bracketed paste mode on demand --- src/fe-text/gui-readline.c | 3 +++ src/fe-text/term-terminfo.c | 8 ++++++++ src/fe-text/term.h | 2 ++ 3 files changed, 13 insertions(+) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index c4c0064e..91dec4ea 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -969,6 +969,9 @@ static void setup_changed(void) paste_verify_line_count = settings_get_int("paste_verify_line_count"); paste_join_multiline = settings_get_bool("paste_join_multiline"); paste_use_bracketed_mode = settings_get_bool("paste_use_bracketed_mode"); + + /* Enable the bracketed paste mode on demand */ + term_set_bracketed_paste_mode(paste_use_bracketed_mode); } void gui_readline_init(void) diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c index ded79c28..9376bda8 100644 --- a/src/fe-text/term-terminfo.c +++ b/src/fe-text/term-terminfo.c @@ -689,3 +689,11 @@ 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/term.h b/src/fe-text/term.h index cdcc787a..692ce9c5 100644 --- a/src/fe-text/term.h +++ b/src/fe-text/term.h @@ -94,6 +94,8 @@ void term_refresh(TERM_WINDOW *window); void term_stop(void); +void term_set_bracketed_paste_mode(int enable); + /* keyboard input handling */ void term_set_input_type(int type); void term_gets(GArray *buffer, int *line_count); From 6888fc5fc74936af74fd30042e45652951648ea4 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 9 Sep 2015 22:41:17 +0200 Subject: [PATCH 0158/1650] Get rid of the non-portable memmem The sequences we're after are found at the beginning or at the end of the buffer, there's no need to scan the whole thing. --- src/fe-text/gui-readline.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 91dec4ea..87c824cf 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -666,15 +666,11 @@ static void sig_input(void) /* use the bracketed paste mode to detect when the user pastes * some text into the entry */ if (paste_use_bracketed_mode != FALSE && paste_buffer->len > 12) { - /* try to find the start/end sequence */ - int seq_start = memmem(paste_buffer->data, - paste_buffer->len * g_array_get_element_size(paste_buffer), - bp_start, sizeof(bp_start)) != NULL, - seq_end = memmem(paste_buffer->data, - paste_buffer->len * g_array_get_element_size(paste_buffer), - bp_end, sizeof(bp_end)) != NULL; - - g_warning("found sequences : start %d end %d", seq_start, seq_end); + /* try to find the start/end sequence, we know that we + * either find those at the start/end of the buffer or + * we don't find those at all. */ + int seq_start = !memcmp(paste_buffer->data, bp_start, sizeof(bp_start)), + seq_end = !memcmp(paste_buffer->data + paste_buffer->len * g_array_get_element_size(paste_buffer) - sizeof(bp_end), bp_end, sizeof(bp_end)); if (seq_start) { paste_bracketed_mode = TRUE; From 9a6b2dedcce165211892b39cf7455314dfde57fb Mon Sep 17 00:00:00 2001 From: dequis Date: Thu, 17 Sep 2015 00:52:55 -0300 Subject: [PATCH 0159/1650] Improve bracketed paste start/end detection - Use a keybinding to detect the start of a bracketed paste - Iterate over the paste buffer looking for the end marker --- src/fe-text/gui-readline.c | 50 +++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 87c824cf..51b9f758 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -665,37 +665,44 @@ static void sig_input(void) /* use the bracketed paste mode to detect when the user pastes * some text into the entry */ - if (paste_use_bracketed_mode != FALSE && paste_buffer->len > 12) { - /* try to find the start/end sequence, we know that we - * either find those at the start/end of the buffer or - * we don't find those at all. */ - int seq_start = !memcmp(paste_buffer->data, bp_start, sizeof(bp_start)), - seq_end = !memcmp(paste_buffer->data + paste_buffer->len * g_array_get_element_size(paste_buffer) - sizeof(bp_end), bp_end, sizeof(bp_end)); + if (paste_bracketed_mode) { + int i; + int len = paste_buffer->len - G_N_ELEMENTS(bp_end); + unichar *ptr = (unichar *) paste_buffer->data; - if (seq_start) { - paste_bracketed_mode = TRUE; - /* remove the leading sequence chars */ - g_array_remove_range(paste_buffer, 0, 6); + if (len <= 0) { + return; } - if (seq_end) { - paste_bracketed_mode = FALSE; - /* remove the trailing sequence chars */ - g_array_set_size(paste_buffer, paste_buffer->len - 6); - /* decide what to do with the buffer */ - paste_timeout(NULL); + for (i = 0; i <= len; i++, ptr++) { + if (ptr[0] == bp_end[0] && !memcmp(ptr, bp_end, sizeof(bp_end))) { + /* remove the trailing sequence chars */ + g_array_set_size(paste_buffer, i); + + /* decide what to do with the buffer */ + paste_timeout(NULL); + + paste_bracketed_mode = FALSE; + break; + } } } else if (paste_detect_time > 0 && paste_buffer->len >= 3) { if (paste_timeout_id != -1) g_source_remove(paste_timeout_id); paste_timeout_id = g_timeout_add(paste_detect_time, paste_timeout, NULL); - } else { + } else if (!paste_bracketed_mode) { int i; for (i = 0; i < paste_buffer->len; i++) { unichar key = g_array_index(paste_buffer, unichar, i); signal_emit("gui key pressed", 1, GINT_TO_POINTER(key)); + + if (paste_bracketed_mode) { + /* just enabled by the signal, remove what was processed so far */ + g_array_remove_range(paste_buffer, 0, i + 1); + return; + } } g_array_set_size(paste_buffer, 0); paste_line_count = 0; @@ -703,6 +710,11 @@ static void sig_input(void) } } +static void key_paste_start(void) +{ + paste_bracketed_mode = TRUE; +} + time_t get_idle_time(void) { return last_keypress.tv_sec; @@ -1060,6 +1072,8 @@ void gui_readline_init(void) key_bind("key", NULL, "meta2-5F", "cend", (SIGNAL_FUNC) key_combo); key_bind("key", NULL, "meta2-1;5F", "cend", (SIGNAL_FUNC) key_combo); + key_bind("paste_start", "Bracketed paste start", "meta2-200~", "paste_start", (SIGNAL_FUNC) key_paste_start); + /* cursor movement */ key_bind("backward_character", "Move the cursor a character backward", "left", NULL, (SIGNAL_FUNC) key_backward_character); key_bind("forward_character", "Move the cursor a character forward", "right", NULL, (SIGNAL_FUNC) key_forward_character); @@ -1155,6 +1169,8 @@ void gui_readline_deinit(void) key_configure_freeze(); + key_unbind("paste_start", (SIGNAL_FUNC) key_paste_start); + key_unbind("backward_character", (SIGNAL_FUNC) key_backward_character); key_unbind("forward_character", (SIGNAL_FUNC) key_forward_character); key_unbind("backward_word", (SIGNAL_FUNC) key_backward_word); From 52729ca3da6ca594d710f58f252ac6cd6952fab0 Mon Sep 17 00:00:00 2001 From: dequis Date: Thu, 17 Sep 2015 00:54:13 -0300 Subject: [PATCH 0160/1650] Save the part of the paste buffer after the bp_end marker for later Also move relevant code to a paste_bracketed_end() function --- src/fe-text/gui-readline.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 51b9f758..61cdad1a 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -61,6 +61,7 @@ static int paste_detect_time, paste_verify_line_count; static char *paste_entry; static int paste_entry_pos; static GArray *paste_buffer; +static GArray *paste_buffer_rest; static char *paste_old_prompt; static int paste_prompt, paste_line_count; @@ -331,6 +332,12 @@ static void paste_flush(int send) paste_send(); g_array_set_size(paste_buffer, 0); + /* re-add anything that may have been after the bracketed paste end */ + if (paste_buffer_rest->len) { + g_array_append_vals(paste_buffer, paste_buffer_rest->data, paste_buffer_rest->len); + g_array_set_size(paste_buffer_rest, 0); + } + gui_entry_set_prompt(active_entry, paste_old_prompt == NULL ? "" : paste_old_prompt); g_free(paste_old_prompt); paste_old_prompt = NULL; @@ -643,6 +650,26 @@ static gboolean paste_timeout(gpointer data) return FALSE; } +static void paste_bracketed_end(int i, gboolean rest) +{ + /* if there's stuff after the end bracket, save it for later */ + if (rest) { + unichar *start = ((unichar *) paste_buffer->data) + i + G_N_ELEMENTS(bp_end); + int len = paste_buffer->len - G_N_ELEMENTS(bp_end); + + g_array_set_size(paste_buffer_rest, 0); + g_array_append_vals(paste_buffer_rest, start, len); + } + + /* remove the rest, including the trailing sequence chars */ + g_array_set_size(paste_buffer, i); + + /* decide what to do with the buffer */ + paste_timeout(NULL); + + paste_bracketed_mode = FALSE; +} + static void sig_input(void) { if (!active_entry) { @@ -676,13 +703,7 @@ static void sig_input(void) for (i = 0; i <= len; i++, ptr++) { if (ptr[0] == bp_end[0] && !memcmp(ptr, bp_end, sizeof(bp_end))) { - /* remove the trailing sequence chars */ - g_array_set_size(paste_buffer, i); - - /* decide what to do with the buffer */ - paste_timeout(NULL); - - paste_bracketed_mode = FALSE; + paste_bracketed_end(i, i != len); break; } } @@ -993,6 +1014,7 @@ void gui_readline_init(void) paste_entry = NULL; paste_entry_pos = 0; paste_buffer = g_array_new(FALSE, FALSE, sizeof(unichar)); + paste_buffer_rest = g_array_new(FALSE, FALSE, sizeof(unichar)); paste_old_prompt = NULL; paste_timeout_id = -1; paste_bracketed_mode = FALSE; @@ -1228,6 +1250,7 @@ void gui_readline_deinit(void) key_unbind("stop_irc", (SIGNAL_FUNC) key_sig_stop); keyboard_destroy(keyboard); g_array_free(paste_buffer, TRUE); + g_array_free(paste_buffer_rest, TRUE); key_configure_thaw(); From 3b01198f0306676425f2bf90db2ca9c7179b014e Mon Sep 17 00:00:00 2001 From: dequis Date: Fri, 25 Sep 2015 01:37:06 -0300 Subject: [PATCH 0161/1650] paste_bracketed_end: Fix rest length calculation --- src/fe-text/gui-readline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 61cdad1a..8d571041 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -655,7 +655,7 @@ static void paste_bracketed_end(int i, gboolean rest) /* if there's stuff after the end bracket, save it for later */ if (rest) { unichar *start = ((unichar *) paste_buffer->data) + i + G_N_ELEMENTS(bp_end); - int len = paste_buffer->len - G_N_ELEMENTS(bp_end); + int len = paste_buffer->len - i - G_N_ELEMENTS(bp_end); g_array_set_size(paste_buffer_rest, 0); g_array_append_vals(paste_buffer_rest, start, len); From 79987d87f37f37ce07171ad4c6b94ffbab77b36d Mon Sep 17 00:00:00 2001 From: dequis Date: Fri, 25 Sep 2015 02:21:27 -0300 Subject: [PATCH 0162/1650] Send last line of bracketed paste together with the rest --- src/fe-text/gui-readline.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 8d571041..7f1ed9ca 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -69,6 +69,7 @@ static int paste_join_multiline; static int paste_timeout_id; static int paste_use_bracketed_mode; static int paste_bracketed_mode; +static int paste_was_bracketed_mode; /* Terminal sequences that surround the input when the terminal has the * bracketed paste mode active. Fror more details see @@ -258,9 +259,16 @@ static void paste_buffer_join_lines(GArray *buf) g_array_set_size(buf, dest - arr); } +static void paste_send_line(char *text) +{ + /* we need to get the current history every time because it might change between calls */ + command_history_add(command_history_current(active_win), text); + + signal_emit("send command", 3, text, active_win->active_server, active_win->active); +} + static void paste_send(void) { - HISTORY_REC *history; unichar *arr; GString *str; char out[10], *text; @@ -285,11 +293,7 @@ static void paste_send(void) } text = gui_entry_get_text(active_entry); - history = command_history_current(active_win); - command_history_add(history, text); - - signal_emit("send command", 3, text, - active_win->active_server, active_win->active); + paste_send_line(text); g_free(text); } @@ -297,12 +301,7 @@ static void paste_send(void) str = g_string_new(NULL); for (; i < paste_buffer->len; i++) { if (arr[i] == '\r' || arr[i] == '\n') { - history = command_history_current(active_win); - command_history_add(history, str->str); - - signal_emit("send command", 3, str->str, - active_win->active_server, - active_win->active); + paste_send_line(str->str); g_string_truncate(str, 0); } else if (active_entry->utf8) { out[g_unichar_to_utf8(arr[i], out)] = '\0'; @@ -316,7 +315,14 @@ static void paste_send(void) } } - gui_entry_set_text(active_entry, str->str); + if (paste_was_bracketed_mode) { + /* the text before the bracket end should be sent along with the rest */ + paste_send_line(str->str); + gui_entry_set_text(active_entry, ""); + } else { + gui_entry_set_text(active_entry, str->str); + } + g_string_free(str, TRUE); } @@ -632,6 +638,8 @@ static void key_delete_to_next_space(void) static gboolean paste_timeout(gpointer data) { + paste_was_bracketed_mode = paste_bracketed_mode; + if (paste_line_count == 0) { int i; From 83f9772e213b6b1e181338738c2997150162c871 Mon Sep 17 00:00:00 2001 From: dequis Date: Fri, 25 Sep 2015 02:23:38 -0300 Subject: [PATCH 0163/1650] Fix some minor style issues --- src/fe-text/gui-readline.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 7f1ed9ca..9b635139 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -710,13 +710,12 @@ static void sig_input(void) } for (i = 0; i <= len; i++, ptr++) { - if (ptr[0] == bp_end[0] && !memcmp(ptr, bp_end, sizeof(bp_end))) { + if (ptr[0] == bp_end[0] && memcmp(ptr, bp_end, sizeof(bp_end)) == 0) { paste_bracketed_end(i, i != len); break; } } - } - else if (paste_detect_time > 0 && paste_buffer->len >= 3) { + } else if (paste_detect_time > 0 && paste_buffer->len >= 3) { if (paste_timeout_id != -1) g_source_remove(paste_timeout_id); paste_timeout_id = g_timeout_add(paste_detect_time, paste_timeout, NULL); From 7d062a313add81584608f2b0abf086f2b73e8098 Mon Sep 17 00:00:00 2001 From: dequis Date: Fri, 25 Sep 2015 02:27:59 -0300 Subject: [PATCH 0164/1650] Create paste_bracketed_middle() function to handle small pastes "Small" as in ending in the same sig_input() call where they started --- src/fe-text/gui-readline.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 9b635139..5d859ede 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -678,6 +678,24 @@ static void paste_bracketed_end(int i, gboolean rest) paste_bracketed_mode = FALSE; } +static void paste_bracketed_middle() +{ + int i; + int len = paste_buffer->len - G_N_ELEMENTS(bp_end); + unichar *ptr = (unichar *) paste_buffer->data; + + if (len <= 0) { + return; + } + + for (i = 0; i <= len; i++, ptr++) { + if (ptr[0] == bp_end[0] && memcmp(ptr, bp_end, sizeof(bp_end)) == 0) { + paste_bracketed_end(i, i != len); + break; + } + } +} + static void sig_input(void) { if (!active_entry) { @@ -701,20 +719,8 @@ static void sig_input(void) /* use the bracketed paste mode to detect when the user pastes * some text into the entry */ if (paste_bracketed_mode) { - int i; - int len = paste_buffer->len - G_N_ELEMENTS(bp_end); - unichar *ptr = (unichar *) paste_buffer->data; + paste_bracketed_middle(); - if (len <= 0) { - return; - } - - for (i = 0; i <= len; i++, ptr++) { - if (ptr[0] == bp_end[0] && memcmp(ptr, bp_end, sizeof(bp_end)) == 0) { - paste_bracketed_end(i, i != len); - break; - } - } } else if (paste_detect_time > 0 && paste_buffer->len >= 3) { if (paste_timeout_id != -1) g_source_remove(paste_timeout_id); @@ -729,6 +735,9 @@ static void sig_input(void) if (paste_bracketed_mode) { /* just enabled by the signal, remove what was processed so far */ g_array_remove_range(paste_buffer, 0, i + 1); + + /* handle single-line / small pastes here */ + paste_bracketed_middle(); return; } } From c721d57688e8f5413df7c179eac54c315343fbb0 Mon Sep 17 00:00:00 2001 From: dequis Date: Fri, 25 Sep 2015 03:09:14 -0300 Subject: [PATCH 0165/1650] Handle a paste start marker right after an end one (ignore both) This actually workarounds a bug with the "st" terminal, for which i've already submitted a patch, but irssi needs to be able to handle it decently too. --- src/fe-text/gui-readline.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 5d859ede..4616e919 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -681,7 +681,8 @@ static void paste_bracketed_end(int i, gboolean rest) static void paste_bracketed_middle() { int i; - int len = paste_buffer->len - G_N_ELEMENTS(bp_end); + int marklen = G_N_ELEMENTS(bp_end); + int len = paste_buffer->len - marklen; unichar *ptr = (unichar *) paste_buffer->data; if (len <= 0) { @@ -690,6 +691,23 @@ static void paste_bracketed_middle() for (i = 0; i <= len; i++, ptr++) { if (ptr[0] == bp_end[0] && memcmp(ptr, bp_end, sizeof(bp_end)) == 0) { + + /* if there are at least 6 bytes after the end, + * check for another start marker right afterwards */ + if (i <= (len - marklen) && + memcmp(ptr + marklen, bp_start, sizeof(bp_start)) == 0) { + + /* remove both markers*/ + g_array_remove_range(paste_buffer, i, marklen * 2); + len -= marklen * 2; + + /* go one step back */ + if (i > 0) { + i--; + ptr--; + } + continue; + } paste_bracketed_end(i, i != len); break; } From 7866d2bcd6797b8279238ffb2f710bd9ea599cc8 Mon Sep 17 00:00:00 2001 From: dequis Date: Fri, 25 Sep 2015 03:22:02 -0300 Subject: [PATCH 0166/1650] Handle empty bracketed pastes (or sequences of those) Both cases were off-by-one mistakes erring on the side of being too conservative. This fixes these two harmless issues: - For a single empty paste, it required another keystroke before processing it - For a sequence of themcase, a single '~' was left in the input --- src/fe-text/gui-readline.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 4616e919..6e169b93 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -685,7 +685,7 @@ static void paste_bracketed_middle() int len = paste_buffer->len - marklen; unichar *ptr = (unichar *) paste_buffer->data; - if (len <= 0) { + if (len < 0) { return; } @@ -702,10 +702,8 @@ static void paste_bracketed_middle() len -= marklen * 2; /* go one step back */ - if (i > 0) { - i--; - ptr--; - } + i--; + ptr--; continue; } paste_bracketed_end(i, i != len); From 0f066aac11e9a56f394330a8d7dab3428594a623 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 28 Sep 2015 08:54:19 +0530 Subject: [PATCH 0167/1650] Remove Typo from FAQs --- docs/startup-HOWTO.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/startup-HOWTO.html b/docs/startup-HOWTO.html index 30caf657..deff3116 100644 --- a/docs/startup-HOWTO.html +++ b/docs/startup-HOWTO.html @@ -391,7 +391,7 @@ messages window.

the connection into some window. IRSSI DOES NOT. There is no required relationship between window and server. You can connect to 10 servers and manage them all in just one window, or join channel in each one of -them to one sigle window if you really want to. That being said, here's +them to one single window if you really want to. That being said, here's how you do connect to new server without closing the old connection:


From cff536ab7091e79747352ff1f1d1d832870b2fb4 Mon Sep 17 00:00:00 2001
From: Jari Matilainen 
Date: Tue, 29 Sep 2015 10:39:49 +0200
Subject: [PATCH 0168/1650] Add sasl info to /network list output if available

---
 src/fe-common/irc/fe-ircnet.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index dab6f57f..c341081a 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -56,6 +56,11 @@ static void cmd_network_list(void)
 			g_string_append_printf(str, "autosendcmd: %s, ", rec->autosendcmd);
 		if (rec->usermode != NULL)
 			g_string_append_printf(str, "usermode: %s, ", rec->usermode);
+		if (rec->sasl_username != NULL) {
+			g_string_append_printf(str, "sasl_mechanism: %s, ", rec->sasl_mechanism);
+			g_string_append_printf(str, "sasl_username: %s, ", rec->sasl_username);
+			g_string_append_printf(str, "sasl_password: (pass), ");
+		}
 
 		if (rec->cmd_queue_speed > 0)
 			g_string_append_printf(str, "cmdspeed: %d, ", rec->cmd_queue_speed);

From b04b5f0f1d03be6282f7ba835b8a4f29b18b9c69 Mon Sep 17 00:00:00 2001
From: Jari Matilainen 
Date: Tue, 29 Sep 2015 11:44:11 +0200
Subject: [PATCH 0169/1650] Make sure sasl settings are defined before printing
 them out

---
 src/fe-common/irc/fe-ircnet.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index c341081a..bb0af313 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -56,12 +56,12 @@ static void cmd_network_list(void)
 			g_string_append_printf(str, "autosendcmd: %s, ", rec->autosendcmd);
 		if (rec->usermode != NULL)
 			g_string_append_printf(str, "usermode: %s, ", rec->usermode);
-		if (rec->sasl_username != NULL) {
+		if (rec->sasl_mechanism != NULL)
 			g_string_append_printf(str, "sasl_mechanism: %s, ", rec->sasl_mechanism);
+		if (rec->sasl_username != NULL)
 			g_string_append_printf(str, "sasl_username: %s, ", rec->sasl_username);
+		if (rec->sasl_password != NULL)
 			g_string_append_printf(str, "sasl_password: (pass), ");
-		}
-
 		if (rec->cmd_queue_speed > 0)
 			g_string_append_printf(str, "cmdspeed: %d, ", rec->cmd_queue_speed);
 		if (rec->max_cmds_at_once > 0)

From 00176dbff5af1a649a1f45972c45d661912aa8be Mon Sep 17 00:00:00 2001
From: Jellyfrog 
Date: Tue, 29 Sep 2015 17:34:35 +0200
Subject: [PATCH 0170/1650] Switch to modern Travis CI infrastructure

Fixes #310
---
 .travis.yml | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 35226645..aa807a7b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,4 @@
+sudo: false
 language: perl
 perl:
     - "5.20-shrplib"
@@ -7,19 +8,22 @@ env:
     - CC=clang
     - CC=gcc
 
+addons:
+    apt:
+        packages:
+            - libperl-dev
+            - elinks
+
 before_install:
-    - sudo apt-get update -qq
     - perl -V
-    - sudo apt-get build-dep -qq irssi
-    - sudo apt-get install -qq lynx
 
 install: true
 
 script:
-    - ./autogen.sh --with-proxy --with-bot --with-perl=module
+    - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build --enable-silent-rules
     - cat config.log
     - make
-    - sudo make install
+    - make install
 
 notifications:
     irc:

From 2ad6bb12955b3e9bfa43628e6dbfc984537f8b26 Mon Sep 17 00:00:00 2001
From: isundil 
Date: Thu, 1 Oct 2015 21:14:30 +0200
Subject: [PATCH 0171/1650] Fix #45 Make it easy to delete default channels,
 servers and networks Removing network will now also remove all attached
 servers

---
 src/core/servers-setup.c      | 18 ++++++++++++++++++
 src/core/servers-setup.h      |  4 ++++
 src/fe-common/irc/fe-ircnet.c |  6 ++++++
 3 files changed, 28 insertions(+)

diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index 90a447d4..74b818e7 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -333,6 +333,24 @@ server_create_conn(int chat_type, const char *dest, int port,
 				chatnet, password, nick);
 }
 
+GSList *server_setup_find_chatnet(const char *chatnet)
+{
+	GSList *servers;
+	GSList *tmp;
+
+	g_return_val_if_fail(chatnet != NULL, NULL);
+
+	servers = NULL;
+	for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
+		SERVER_SETUP_REC *rec = tmp->data;
+
+		if (g_ascii_strcasecmp(rec->chatnet, chatnet) == 0)
+			servers = g_slist_append(servers, rec);
+	}
+
+	return servers;
+}
+
 /* Find matching server from setup. Try to find record with a same port,
    but fallback to any server with the same address. */
 SERVER_SETUP_REC *server_setup_find(const char *address, int port,
diff --git a/src/core/servers-setup.h b/src/core/servers-setup.h
index f7601a68..dffaec02 100644
--- a/src/core/servers-setup.h
+++ b/src/core/servers-setup.h
@@ -36,6 +36,10 @@ server_create_conn(int chat_type, const char *dest, int port,
 SERVER_SETUP_REC *server_setup_find(const char *address, int port,
 				    const char *chatnet);
 
+/* Find all servers matching chatnet.
+   Return a list of SERVER_SETUP_REC */
+GSList *server_setup_find_chatnet(const char *chatnet);
+
 void server_setup_add(SERVER_SETUP_REC *rec);
 void server_setup_remove(SERVER_SETUP_REC *rec);
 
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index bb0af313..1760b966 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -176,6 +176,8 @@ static void cmd_network_add(const char *data)
 static void cmd_network_remove(const char *data)
 {
 	IRC_CHATNET_REC *rec;
+	GSList *servers;
+	GSList *tmp;
 
 	if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
 
@@ -183,6 +185,10 @@ static void cmd_network_remove(const char *data)
 	if (rec == NULL)
 		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NETWORK_NOT_FOUND, data);
 	else {
+		servers = server_setup_find_chatnet(data);
+
+		for (tmp = servers; tmp != NULL; tmp = tmp->next)
+			server_setup_remove((SERVER_SETUP_REC *) tmp->data);
 		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NETWORK_REMOVED, data);
 		chatnet_remove(CHATNET(rec));
 	}

From 6ca7dc68478772258dea114d29625dc2c87999f9 Mon Sep 17 00:00:00 2001
From: isundil 
Date: Thu, 1 Oct 2015 22:36:02 +0200
Subject: [PATCH 0172/1650] Updated server removal Removing network will also
 remove attached channels

---
 src/core/channels-setup.c     | 15 +++++++++++++++
 src/core/channels-setup.h     |  3 +++
 src/core/servers-setup.c      | 33 +++++++++++++++------------------
 src/core/servers-setup.h      |  7 +++----
 src/fe-common/irc/fe-ircnet.c | 10 ++++------
 5 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/src/core/channels-setup.c b/src/core/channels-setup.c
index b2d971dd..2902ef8e 100644
--- a/src/core/channels-setup.c
+++ b/src/core/channels-setup.c
@@ -86,6 +86,21 @@ static void channel_setup_destroy(CHANNEL_SETUP_REC *channel)
 	g_free(channel);
 }
 
+void channel_setup_remove_chatnet(const char *chatnet)
+{
+	GSList *tmp, *next;
+
+	g_return_if_fail(chatnet != NULL);
+
+	for (tmp = setupchannels; tmp != NULL; tmp = next) {
+		CHANNEL_SETUP_REC *rec = tmp->data;
+
+		next = tmp->next;
+		if (g_ascii_strcasecmp(rec->chatnet, chatnet) == 0)
+			channel_setup_remove(rec);
+	}
+}
+
 void channel_setup_remove(CHANNEL_SETUP_REC *channel)
 {
         channel_config_remove(channel);
diff --git a/src/core/channels-setup.h b/src/core/channels-setup.h
index 61b828b2..3bb7da7f 100644
--- a/src/core/channels-setup.h
+++ b/src/core/channels-setup.h
@@ -21,6 +21,9 @@ void channels_setup_deinit(void);
 void channel_setup_create(CHANNEL_SETUP_REC *channel);
 void channel_setup_remove(CHANNEL_SETUP_REC *channel);
 
+/* Remove channels attached to chatnet */
+void channel_setup_remove_chatnet(const char *chatnet);
+
 CHANNEL_SETUP_REC *channel_setup_find(const char *channel,
 				      const char *chatnet);
 
diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index 74b818e7..cd5fe406 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -333,24 +333,6 @@ server_create_conn(int chat_type, const char *dest, int port,
 				chatnet, password, nick);
 }
 
-GSList *server_setup_find_chatnet(const char *chatnet)
-{
-	GSList *servers;
-	GSList *tmp;
-
-	g_return_val_if_fail(chatnet != NULL, NULL);
-
-	servers = NULL;
-	for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
-		SERVER_SETUP_REC *rec = tmp->data;
-
-		if (g_ascii_strcasecmp(rec->chatnet, chatnet) == 0)
-			servers = g_slist_append(servers, rec);
-	}
-
-	return servers;
-}
-
 /* Find matching server from setup. Try to find record with a same port,
    but fallback to any server with the same address. */
 SERVER_SETUP_REC *server_setup_find(const char *address, int port,
@@ -523,6 +505,21 @@ void server_setup_add(SERVER_SETUP_REC *rec)
 	signal_emit("server setup updated", 1, rec);
 }
 
+void server_setup_remove_chatnet(const char *chatnet)
+{
+	GSList *tmp, *next;
+
+	g_return_val_if_fail(chatnet != NULL, NULL);
+
+	for (tmp = setupservers; tmp != NULL; tmp = next) {
+		SERVER_SETUP_REC *rec = tmp->data;
+
+		next = tmp->next;
+		if (g_ascii_strcasecmp(rec->chatnet, chatnet) == 0)
+			server_setup_remove(rec);
+	}
+}
+
 void server_setup_remove(SERVER_SETUP_REC *rec)
 {
 	server_setup_remove_config(rec);
diff --git a/src/core/servers-setup.h b/src/core/servers-setup.h
index dffaec02..e7ff7abf 100644
--- a/src/core/servers-setup.h
+++ b/src/core/servers-setup.h
@@ -36,13 +36,12 @@ server_create_conn(int chat_type, const char *dest, int port,
 SERVER_SETUP_REC *server_setup_find(const char *address, int port,
 				    const char *chatnet);
 
-/* Find all servers matching chatnet.
-   Return a list of SERVER_SETUP_REC */
-GSList *server_setup_find_chatnet(const char *chatnet);
-
 void server_setup_add(SERVER_SETUP_REC *rec);
 void server_setup_remove(SERVER_SETUP_REC *rec);
 
+/* Remove servers attached to chatne */
+void server_setup_remove_chatnet(const char *chatnet);
+
 void servers_setup_init(void);
 void servers_setup_deinit(void);
 
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index 1760b966..4d7037d5 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -29,6 +29,8 @@
 #include "irc-servers.h"
 #include "irc-chatnets.h"
 #include "printtext.h"
+#include "servers-setup.h"
+#include "channels-setup.h"
 
 static void cmd_network_list(void)
 {
@@ -176,8 +178,6 @@ static void cmd_network_add(const char *data)
 static void cmd_network_remove(const char *data)
 {
 	IRC_CHATNET_REC *rec;
-	GSList *servers;
-	GSList *tmp;
 
 	if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
 
@@ -185,10 +185,8 @@ static void cmd_network_remove(const char *data)
 	if (rec == NULL)
 		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NETWORK_NOT_FOUND, data);
 	else {
-		servers = server_setup_find_chatnet(data);
-
-		for (tmp = servers; tmp != NULL; tmp = tmp->next)
-			server_setup_remove((SERVER_SETUP_REC *) tmp->data);
+		server_setup_remove_chatnet(data);
+		channel_setup_remove_chatnet(data);
 		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NETWORK_REMOVED, data);
 		chatnet_remove(CHATNET(rec));
 	}

From ef1a09b87d5df7fcaeced70e09312c225d99c4b6 Mon Sep 17 00:00:00 2001
From: isundil 
Date: Thu, 1 Oct 2015 22:53:34 +0200
Subject: [PATCH 0173/1650] Fix return value of server_setup_remove_chatnet

---
 src/core/servers-setup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index cd5fe406..771e3999 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -509,7 +509,7 @@ void server_setup_remove_chatnet(const char *chatnet)
 {
 	GSList *tmp, *next;
 
-	g_return_val_if_fail(chatnet != NULL, NULL);
+	g_return_if_fail(chatnet != NULL);
 
 	for (tmp = setupservers; tmp != NULL; tmp = next) {
 		SERVER_SETUP_REC *rec = tmp->data;

From a475d57183bcbfd6e540dba5cd7894d8c38b53b7 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Thu, 1 Oct 2015 22:25:40 +0200
Subject: [PATCH 0174/1650] Save the sasl state in the session

This is seemingly required to have irssi re-authenticate after a
restart.
---
 src/irc/core/irc-session.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/irc/core/irc-session.c b/src/irc/core/irc-session.c
index ea65d8a5..18e8e5c7 100644
--- a/src/irc/core/irc-session.c
+++ b/src/irc/core/irc-session.c
@@ -28,6 +28,8 @@
 #include "irc-channels.h"
 #include "irc-nicklist.h"
 
+#include "sasl.h"
+
 struct _isupport_data { CONFIG_REC *config; CONFIG_NODE *node; };
 
 static void session_isupport_foreach(char *key, char *value, struct _isupport_data *data)
@@ -65,6 +67,10 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
 	config_node_set_str(config, node, "away_reason", server->away_reason);
 	config_node_set_bool(config, node, "emode_known", server->emode_known);
 
+	config_node_set_int(config, node, "sasl_mechanism", server->connrec->sasl_mechanism);
+	config_node_set_str(config, node, "sasl_username", server->connrec->sasl_username);
+	config_node_set_str(config, node, "sasl_password", server->connrec->sasl_password);
+
 	config_node_set_bool(config, node, "isupport_sent", server->isupport_sent);
 	isupport = config_node_section(config, node, "isupport", NODE_TYPE_BLOCK);
         isupport_data.config = config;
@@ -90,6 +96,15 @@ static void sig_session_restore_server(IRC_SERVER_REC *server,
 	server->emode_known = config_node_get_bool(node, "emode_known", FALSE);
 	server->isupport_sent = config_node_get_bool(node, "isupport_sent", FALSE);
 
+	server->connrec->sasl_mechanism = config_node_get_int(node, "sasl_mechanism", SASL_MECHANISM_NONE);
+	/* The fields below might have been filled when loading the chatnet
+	 * description from the config and we favor the content that's been saved
+	 * in the session file over that. */
+	g_free(server->connrec->sasl_username);
+	server->connrec->sasl_username = g_strdup(config_node_get_str(node, "sasl_username", NULL));
+	g_free(server->connrec->sasl_password);
+	server->connrec->sasl_password = g_strdup(config_node_get_str(node, "sasl_password", NULL));
+
 	if (server->isupport == NULL) {
 		server->isupport = g_hash_table_new((GHashFunc) g_istr_hash,
 						    (GCompareFunc) g_istr_equal);

From cfff402fe677316d286ce6663b8afeee4be95526 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Fri, 2 Oct 2015 11:25:30 +0200
Subject: [PATCH 0175/1650] Don't set the usermode field if blank

Fixes FS#919
---
 src/irc/core/irc-chatnets.c      |  5 ++++-
 src/irc/core/irc-servers-setup.c | 12 +++++++++---
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/src/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c
index d72f71dd..0796e0cb 100644
--- a/src/irc/core/irc-chatnets.c
+++ b/src/irc/core/irc-chatnets.c
@@ -35,10 +35,13 @@ void ircnet_create(IRC_CHATNET_REC *rec)
 
 static void sig_chatnet_read(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
 {
+	char *value;
+
 	if (!IS_IRC_CHATNET(rec))
 		return;
 
-	rec->usermode = g_strdup(config_node_get_str(node, "usermode", NULL));
+	value = config_node_get_str(node, "usermode", NULL);
+	rec->usermode = (value != NULL && *value != '\0') ? g_strdup(value) : NULL;
 
 	rec->max_cmds_at_once = config_node_get_int(node, "cmdmax", 0);
 	rec->cmd_queue_speed = config_node_get_int(node, "cmdspeed", 0);
diff --git a/src/irc/core/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c
index bf1d2ddf..f425b587 100644
--- a/src/irc/core/irc-servers-setup.c
+++ b/src/irc/core/irc-servers-setup.c
@@ -48,12 +48,18 @@ static void sig_server_setup_fill_reconn(IRC_SERVER_CONNECT_REC *conn,
 
 static void sig_server_setup_fill_connect(IRC_SERVER_CONNECT_REC *conn)
 {
+	const char *value;
+
 	if (!IS_IRC_SERVER_CONNECT(conn))
 		return;
 
-	conn->alternate_nick = *settings_get_str("alternate_nick") != '\0' ?
-		g_strdup(settings_get_str("alternate_nick")) : NULL;
-        conn->usermode = g_strdup(settings_get_str("usermode"));
+	value = settings_get_str("alternate_nick");
+	conn->alternate_nick = (value != NULL && *value != '\0') ?
+		g_strdup(value) : NULL;
+
+	value = settings_get_str("usermode");
+	conn->usermode = (value != NULL && *value != '\0') ?
+		g_strdup(value) : NULL;
 }
 
 static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,

From b545bc96a9e1a875beb50d9202161864ca8164d8 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Fri, 2 Oct 2015 12:39:08 +0200
Subject: [PATCH 0176/1650] Fix a memory leak.

g_get_current_dir() returns a heap-allocated string.
---
 src/core/core.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/core/core.c b/src/core/core.c
index b9debbb5..879d346f 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -156,11 +156,17 @@ static void sig_init_finished(void)
 static char *fix_path(const char *str)
 {
 	char *new_str = convert_home(str);
+
 	if (!g_path_is_absolute(new_str)) {
 		char *tmp_str = new_str;
-		new_str = g_strdup_printf("%s/%s", g_get_current_dir(), tmp_str);
+		char *current_dir = g_get_current_dir();
+
+		new_str = g_build_path(G_DIR_SEPARATOR_S, current_dir, tmp_str);
+
+		g_free(current_dir);
 		g_free(tmp_str);
 	}
+
 	return new_str;
 }
 

From 2e860abd2b8b3a30f74005450830c34a318b64a3 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Fri, 2 Oct 2015 14:04:04 +0200
Subject: [PATCH 0177/1650] Fix the display of utf8 sequences in the gui

term_addstr() had a long-standing fixme that suggested it didn't
take into account the string encoding when calculating the string
length.
The BIG5 code path is untested.
---
 src/fe-common/core/utf8.h   |  2 ++
 src/fe-text/gui-printtext.c |  7 +++--
 src/fe-text/term-terminfo.c | 53 ++++++++++++++++++++++++++++++++++---
 src/fe-text/term.h          |  2 +-
 4 files changed, 55 insertions(+), 9 deletions(-)

diff --git a/src/fe-common/core/utf8.h b/src/fe-common/core/utf8.h
index 3c15dc7d..70b44d7e 100644
--- a/src/fe-common/core/utf8.h
+++ b/src/fe-common/core/utf8.h
@@ -8,6 +8,8 @@
 #define is_big5_hi(hi)  (0x81 <= (hi) && (hi) <= 0xFE)
 #define is_big5(hi,lo) (is_big5_hi(hi) && is_big5_lo(lo))
 
+int strlen_big5(const unsigned char *str);
+
 /* Returns width for character (0-2). */
 int mk_wcwidth(unichar c);
 
diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c
index 547d39c9..d8272df5 100644
--- a/src/fe-text/gui-printtext.c
+++ b/src/fe-text/gui-printtext.c
@@ -220,16 +220,15 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
 	get_colors(flags, &fg, &bg, &attr);
 
 	if (window == NULL) {
-                g_return_if_fail(next_xpos != -1);
+		g_return_if_fail(next_xpos != -1);
 
 		term_set_color2(root_window, attr, fg, bg);
 
 		term_move(root_window, next_xpos, next_ypos);
 		if (flags & GUI_PRINT_FLAG_CLRTOEOL)
 			term_clrtoeol(root_window);
-		term_addstr(root_window, str);
-		next_xpos += strlen(str); /* FIXME utf8 or big5 */
-                return;
+		next_xpos += term_addstr(root_window, str);
+		return;
 	}
 
 	lineinfo.level = dest == NULL ? 0 : dest->level;
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index ded79c28..8c95bc0d 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -522,15 +522,60 @@ void term_add_unichar(TERM_WINDOW *window, unichar chr)
 	}
 }
 
-void term_addstr(TERM_WINDOW *window, const char *str)
+int term_addstr(TERM_WINDOW *window, const char *str)
 {
-	int len;
+	int i, len, raw_len;
+	unichar *tmp;
+	const char *ptr;
 
 	if (vcmove) term_move_real();
-	len = strlen(str); /* FIXME utf8 or big5 */
+
+	raw_len = strlen(str);
+
+	/* The string length depends on the terminal encoding */
+	switch (term_type) {
+	case TERM_TYPE_BIG5:
+		len = strlen_big5((const unsigned char *)str);
+		break;
+	case TERM_TYPE_UTF8:
+		len = g_utf8_strlen(str, -1);
+		break;
+	default:
+		len = strlen(str);
+		break;
+	}
+
+	tmp = calloc(len, sizeof(unichar));
+	if (tmp == NULL)
+	    return 0;
+
+	switch (term_type) {
+	case TERM_TYPE_BIG5:
+	    big5_to_unichars(str, tmp);
+	    break;
+	case TERM_TYPE_UTF8:
+	    ptr = str;
+	    for (i = 0; i < len; i++) {
+		tmp[i] = g_utf8_get_char(ptr);
+		ptr = g_utf8_next_char(ptr);
+	    }
+	    break;
+	default:
+	    for (i = 0; i < len; i++)
+		tmp[i] = str[i];
+	}
+
+	for (len = i = 0; i < len; i++)
+	    len += unichar_isprint(tmp[i]) ? mk_wcwidth(tmp[i]) : 1;
+
+	free(tmp);
+
         term_printed_text(len);
 
-	fwrite(str, 1, len, window->term->out);
+	/* Use strlen() here since we need the number of raw bytes */
+	fwrite(str, 1, raw_len, window->term->out);
+
+	return len;
 }
 
 void term_clrtoeol(TERM_WINDOW *window)
diff --git a/src/fe-text/term.h b/src/fe-text/term.h
index cdcc787a..f0a76c42 100644
--- a/src/fe-text/term.h
+++ b/src/fe-text/term.h
@@ -83,7 +83,7 @@ void term_set_color(TERM_WINDOW *window, int col);
 void term_move(TERM_WINDOW *window, int x, int y);
 void term_addch(TERM_WINDOW *window, char chr);
 void term_add_unichar(TERM_WINDOW *window, unichar chr);
-void term_addstr(TERM_WINDOW *window, const char *str);
+int  term_addstr(TERM_WINDOW *window, const char *str);
 void term_clrtoeol(TERM_WINDOW *window);
 
 void term_move_cursor(int x, int y);

From c351c448b8dd2b9759e46c0c6e73ed5ead936ffc Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Fri, 2 Oct 2015 15:02:43 +0200
Subject: [PATCH 0178/1650] Rework the logic to avoid allocating memory

---
 src/fe-text/term-terminfo.c | 52 ++++++++++++++-----------------------
 1 file changed, 19 insertions(+), 33 deletions(-)

diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 8c95bc0d..2ee69a1c 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -524,52 +524,38 @@ void term_add_unichar(TERM_WINDOW *window, unichar chr)
 
 int term_addstr(TERM_WINDOW *window, const char *str)
 {
-	int i, len, raw_len;
-	unichar *tmp;
+	int len, raw_len;
+	unichar tmp;
 	const char *ptr;
 
 	if (vcmove) term_move_real();
 
+	len = 0;
 	raw_len = strlen(str);
 
 	/* The string length depends on the terminal encoding */
-	switch (term_type) {
-	case TERM_TYPE_BIG5:
-		len = strlen_big5((const unsigned char *)str);
-		break;
-	case TERM_TYPE_UTF8:
-		len = g_utf8_strlen(str, -1);
-		break;
-	default:
-		len = strlen(str);
-		break;
-	}
 
-	tmp = calloc(len, sizeof(unichar));
-	if (tmp == NULL)
-	    return 0;
+	ptr = str;
 
-	switch (term_type) {
-	case TERM_TYPE_BIG5:
-	    big5_to_unichars(str, tmp);
-	    break;
-	case TERM_TYPE_UTF8:
-	    ptr = str;
-	    for (i = 0; i < len; i++) {
-		tmp[i] = g_utf8_get_char(ptr);
+	if (term_type != TERM_TYPE_BIG5) {
+	    while (*ptr != '\0') {
+		tmp = g_utf8_get_char(ptr);
+		len += unichar_isprint(tmp) ? mk_wcwidth(tmp) : 1;
 		ptr = g_utf8_next_char(ptr);
 	    }
-	    break;
-	default:
-	    for (i = 0; i < len; i++)
-		tmp[i] = str[i];
+	} else {
+	    while (*ptr != '\0') {
+		if (is_big5(ptr[0], ptr[1])) {
+		    tmp = ptr[0] << 8 | ptr[1];
+		    ptr += 2;
+		} else {
+		    tmp = *ptr;
+		    ptr += 1;
+		}
+		len += (tmp > 0xff) ? 2 : 1; 
+	    }
 	}
 
-	for (len = i = 0; i < len; i++)
-	    len += unichar_isprint(tmp[i]) ? mk_wcwidth(tmp[i]) : 1;
-
-	free(tmp);
-
         term_printed_text(len);
 
 	/* Use strlen() here since we need the number of raw bytes */

From c7646dc58d1e70abc8d2981e08baa83e459affdb Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Fri, 2 Oct 2015 15:07:59 +0200
Subject: [PATCH 0179/1650] Even simpler logic

---
 src/fe-text/term-terminfo.c | 14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)

diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 2ee69a1c..6d289cfc 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -543,18 +543,8 @@ int term_addstr(TERM_WINDOW *window, const char *str)
 		len += unichar_isprint(tmp) ? mk_wcwidth(tmp) : 1;
 		ptr = g_utf8_next_char(ptr);
 	    }
-	} else {
-	    while (*ptr != '\0') {
-		if (is_big5(ptr[0], ptr[1])) {
-		    tmp = ptr[0] << 8 | ptr[1];
-		    ptr += 2;
-		} else {
-		    tmp = *ptr;
-		    ptr += 1;
-		}
-		len += (tmp > 0xff) ? 2 : 1; 
-	    }
-	}
+	} else
+	    len = raw_len;
 
         term_printed_text(len);
 

From 48ab298a67151e6fce33c1d7b34f4f83796b8d9a Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Fri, 2 Oct 2015 15:08:48 +0200
Subject: [PATCH 0180/1650] Kill an unneeded declaration

---
 src/fe-common/core/utf8.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/fe-common/core/utf8.h b/src/fe-common/core/utf8.h
index 70b44d7e..3c15dc7d 100644
--- a/src/fe-common/core/utf8.h
+++ b/src/fe-common/core/utf8.h
@@ -8,8 +8,6 @@
 #define is_big5_hi(hi)  (0x81 <= (hi) && (hi) <= 0xFE)
 #define is_big5(hi,lo) (is_big5_hi(hi) && is_big5_lo(lo))
 
-int strlen_big5(const unsigned char *str);
-
 /* Returns width for character (0-2). */
 int mk_wcwidth(unichar c);
 

From db5ae4adce6ad82150a4fef01c8b141631f89d96 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Fri, 2 Oct 2015 17:13:49 +0200
Subject: [PATCH 0181/1650] Flush the dirty buffer to disk

Given a big enough write_buffer_size and a long enough
write_buffer_timeout it might be possible to show the user an incomplete
or empty awaylog.

Patch by: Petteri Aimonen
---
 src/core/log-away.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/core/log-away.c b/src/core/log-away.c
index 681edcbf..c6de721c 100644
--- a/src/core/log-away.c
+++ b/src/core/log-away.c
@@ -62,6 +62,9 @@ static void awaylog_open(void)
 		return;
 	}
 
+	/* Flush the dirty buffers to disk before acquiring the file position */
+	write_buffer_flush();
+
 	awaylog = log;
 	away_filepos = lseek(log->handle, 0, SEEK_CUR);
 	away_msgs = 0;
@@ -83,6 +86,9 @@ static void awaylog_close(void)
 
 	if (awaylog == log) awaylog = NULL;
 
+	/* Flush the dirty buffers to disk before showing the away log */
+	write_buffer_flush();
+
 	signal_emit("awaylog show", 3, log, GINT_TO_POINTER(away_msgs),
 		    GINT_TO_POINTER(away_filepos));
 	log_close(log);

From ef55e0f6534a5b790131c320fd0490a5beb21a68 Mon Sep 17 00:00:00 2001
From: dequis 
Date: Fri, 2 Oct 2015 13:48:23 -0300
Subject: [PATCH 0182/1650] Add missing null terminator to the g_build_path()
 varargs

Lemon broke it a few commits ago.
---
 src/core/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/core/core.c b/src/core/core.c
index 879d346f..bbeec6f4 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -161,7 +161,7 @@ static char *fix_path(const char *str)
 		char *tmp_str = new_str;
 		char *current_dir = g_get_current_dir();
 
-		new_str = g_build_path(G_DIR_SEPARATOR_S, current_dir, tmp_str);
+		new_str = g_build_path(G_DIR_SEPARATOR_S, current_dir, tmp_str, NULL);
 
 		g_free(current_dir);
 		g_free(tmp_str);

From a66bb95d0e3d76dfb6abda88d6f128540279b461 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= 
Date: Fri, 2 Oct 2015 18:57:06 +0200
Subject: [PATCH 0183/1650] Use silent rules.

---
 .travis.yml  | 2 +-
 configure.ac | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index aa807a7b..f066c17b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,7 +20,7 @@ before_install:
 install: true
 
 script:
-    - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build --enable-silent-rules
+    - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build
     - cat config.log
     - make
     - make install
diff --git a/configure.ac b/configure.ac
index 7bcd3fe7..325b5e5d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,6 +7,8 @@ AC_CONFIG_HEADERS([irssi-config.h])
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE([1.9 no-define foreign])
 
+AM_SILENT_RULES([yes])
+
 AM_MAINTAINER_MODE
 
 AC_PROG_CC

From da3f2f0d0174675faa1a092722e8298460254112 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= 
Date: Fri, 2 Oct 2015 19:51:54 +0200
Subject: [PATCH 0184/1650] Set HOST_NAME_MAX to 255, if it's undefined.

Thanks to Jilles and dx.

Fixes #309
---
 src/irc/core/irc-expandos.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c
index 5d8150f0..62ef577a 100644
--- a/src/irc/core/irc-expandos.c
+++ b/src/irc/core/irc-expandos.c
@@ -27,6 +27,10 @@
 #include "irc-channels.h"
 #include "nicklist.h"
 
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 255
+#endif
+
 static char *last_join;
 
 /* last person to join a channel you are on */
@@ -56,7 +60,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
 {
 	IRC_SERVER_REC *ircserver;
 	const char *username;
-	char hostname[HOST_NAME_MAX];
+	char hostname[HOST_NAME_MAX + 1];
 
 	ircserver = IRC_SERVER(server);
 
@@ -80,7 +84,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
 static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
 {
 	IRC_SERVER_REC *ircserver;
-	char hostname[HOST_NAME_MAX];
+	char hostname[HOST_NAME_MAX + 1];
 	char **list;
 	char *hostname_split;
 

From b68a30cdfe43bec9cdb0e7c822b66d90ccf8982d Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Sat, 3 Oct 2015 14:32:38 +0200
Subject: [PATCH 0185/1650] Include write-buffer.h in log-away.c

Silence a warning and make the world a better place.
---
 src/core/log-away.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/core/log-away.c b/src/core/log-away.c
index c6de721c..e2a0120b 100644
--- a/src/core/log-away.c
+++ b/src/core/log-away.c
@@ -24,6 +24,7 @@
 #include "log.h"
 #include "servers.h"
 #include "settings.h"
+#include "write-buffer.h"
 
 static LOG_REC *awaylog;
 static int away_filepos;

From 48375c3f900f56434441caa0161c0531fd0ce435 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= 
Date: Sat, 3 Oct 2015 18:50:23 +0200
Subject: [PATCH 0186/1650] Simplify Travis config.

---
 .travis.yml | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index f066c17b..c8bbb6d8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,15 +24,3 @@ script:
     - cat config.log
     - make
     - make install
-
-notifications:
-    irc:
-        channels:
-            - "irc.freenode.net#irssi"
-        template:
-            - "%{repository} (%{commit}: %{author}): %{message}"
-            - "Build details : %{build_url}"
-        on_success: always
-        on_failure: always
-        use_notice: true
-        skip_join: true

From 685d8fe5b033ffce40b02aaf4ec3341f5cf3350c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= 
Date: Fri, 2 Oct 2015 20:25:14 +0200
Subject: [PATCH 0187/1650] Add SETTING_TYPE_ANY and replace -1 with it.

---
 src/core/settings.c              |  9 +++++----
 src/core/settings.h              |  3 ++-
 src/fe-common/core/completion.c  |  5 ++---
 src/fe-common/core/fe-settings.c | 31 +++++++++++++++----------------
 4 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/src/core/settings.c b/src/core/settings.c
index b34a5766..8e493124 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -59,7 +59,7 @@ static SETTINGS_REC *settings_get(const char *key, SettingType type)
 		g_warning("settings_get(%s) : not found", key);
 		return NULL;
 	}
-	if (type != -1 && rec->type != type) {
+	if (type != SETTING_TYPE_ANY && rec->type != type) {
 		g_warning("settings_get(%s) : invalid type", key);
 		return NULL;
 	}
@@ -85,7 +85,7 @@ settings_get_str_type(const char *key, SettingType type)
 
 const char *settings_get_str(const char *key)
 {
-	return settings_get_str_type(key, -1);
+	return settings_get_str_type(key, SETTING_TYPE_ANY);
 }
 
 int settings_get_int(const char *key)
@@ -163,6 +163,7 @@ char *settings_get_print(SETTINGS_REC *rec)
 	case SETTING_TYPE_TIME:
 	case SETTING_TYPE_LEVEL:
 	case SETTING_TYPE_SIZE:
+	case SETTING_TYPE_ANY:
 		value = g_strdup(settings_get_str(rec->key));
 		break;
 	}
@@ -380,10 +381,10 @@ SettingType settings_get_type(const char *key)
 {
 	SETTINGS_REC *rec;
 
-	g_return_val_if_fail(key != NULL, -1);
+	g_return_val_if_fail(key != NULL, SETTING_TYPE_ANY);
 
 	rec = g_hash_table_lookup(settings, key);
-	return rec == NULL ? -1 : rec->type;
+	return rec == NULL ? SETTING_TYPE_ANY : rec->type;
 }
 
 /* Get the record of the setting */
diff --git a/src/core/settings.h b/src/core/settings.h
index af00cc80..6f2cf129 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -7,7 +7,8 @@ typedef enum {
 	SETTING_TYPE_BOOLEAN,
 	SETTING_TYPE_TIME,
 	SETTING_TYPE_LEVEL,
-	SETTING_TYPE_SIZE
+	SETTING_TYPE_SIZE,
+	SETTING_TYPE_ANY
 } SettingType;
 
 typedef struct {
diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c
index 312e417c..4461de92 100644
--- a/src/fe-common/core/completion.c
+++ b/src/fe-common/core/completion.c
@@ -362,8 +362,7 @@ static GList *completion_get_settings(const char *key, SettingType type)
 	for (tmp = sets; tmp != NULL; tmp = tmp->next) {
 		SETTINGS_REC *rec = tmp->data;
 
-		if ((type == -1 || rec->type == type) &&
-		    g_ascii_strncasecmp(rec->key, key, len) == 0)
+		if ((type == SETTING_TYPE_ANY || rec->type == type) && g_ascii_strncasecmp(rec->key, key, len) == 0)
 			complist = g_list_insert_sorted(complist, g_strdup(rec->key), (GCompareFunc) g_istr_cmp);
 	}
 	g_slist_free(sets);
@@ -682,7 +681,7 @@ static void sig_complete_set(GList **list, WINDOW_REC *window,
 
 	if (*line == '\0' ||
 	    !g_strcmp0("-clear", line) || !g_strcmp0("-default", line))
-		*list = completion_get_settings(word, -1);
+		*list = completion_get_settings(word, SETTING_TYPE_ANY);
 	else if (*line != '\0' && *word == '\0') {
 		SETTINGS_REC *rec = settings_get_record(line);
 		if (rec != NULL) {
diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index 9c370838..2627989d 100644
--- a/src/fe-common/core/fe-settings.c
+++ b/src/fe-common/core/fe-settings.c
@@ -126,7 +126,7 @@ static void cmd_set(char *data)
 			/* change the setting */
 			switch (rec->type) {
 			case SETTING_TYPE_BOOLEAN:
-                                if (clear)
+				if (clear)
 					settings_set_bool(key, FALSE);
 				else if (set_default)
 					settings_set_bool(key, rec->default_value.v_bool);
@@ -149,32 +149,30 @@ static void cmd_set(char *data)
 			case SETTING_TYPE_TIME:
 				if (!settings_set_time(key, clear ? "0" :
 						       set_default ? rec->default_value.v_string : value))
-					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
-						    TXT_INVALID_TIME);
+					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_INVALID_TIME);
 				break;
 			case SETTING_TYPE_LEVEL:
 				if (!settings_set_level(key, clear ? "" :
 							set_default ? rec->default_value.v_string : value))
-					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
-						    TXT_INVALID_LEVEL);
+					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_INVALID_LEVEL);
 				break;
 			case SETTING_TYPE_SIZE:
 				if (!settings_set_size(key, clear ? "0" :
 						       set_default ? rec->default_value.v_string : value))
-					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
-						    TXT_INVALID_SIZE);
+					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_INVALID_SIZE);
+				break;
+			case SETTING_TYPE_ANY:
+				/* Unpossible! */
 				break;
 			}
 			signal_emit("setup changed", 0);
-			printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
-				    TXT_SET_TITLE, rec->section);
+			printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_SET_TITLE, rec->section);
 			set_print(rec);
 		} else
-			printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
-				    TXT_SET_UNKNOWN, key);
+			printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_SET_UNKNOWN, key);
 	}
 
-        cmd_params_free(free_arg);
+	cmd_params_free(free_arg);
 }
 
 /* SYNTAX: TOGGLE  [on|off|toggle] */
@@ -187,20 +185,21 @@ static void cmd_toggle(const char *data)
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &key, &value))
 		return;
 
-        if (*key == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+	if (*key == '\0')
+		cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
 
 	type = settings_get_type(key);
-        if (type == -1)
+	if (type == SETTING_TYPE_ANY)
 		printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_SET_UNKNOWN, key);
 	else if (type != SETTING_TYPE_BOOLEAN)
 		printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_SET_NOT_BOOLEAN, key);
 	else {
 		set_boolean(key, *value != '\0' ? value : "TOGGLE");
-                set_print(settings_get_record(key));
+		set_print(settings_get_record(key));
 		signal_emit("setup changed", 0);
 	}
 
-        cmd_params_free(free_arg);
+	cmd_params_free(free_arg);
 }
 
 static int config_key_compare(CONFIG_NODE *node1, CONFIG_NODE *node2)

From 5f35fbc57a18eabc68723f1b82aacbfd84f637d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= 
Date: Fri, 2 Oct 2015 20:29:19 +0200
Subject: [PATCH 0188/1650] Remove check for >= 0 for unsigned unichar.

---
 src/fe-text/gui-entry.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 17a7c507..c7d06404 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -35,21 +35,21 @@ static unichar i_toupper(unichar c)
 {
 	if (term_type == TERM_TYPE_UTF8)
 		return g_unichar_toupper(c);
-	return (c >= 0 && c <= 255) ? toupper(c) : c;
+	return c <= 255 ? toupper(c) : c;
 }
 
 static unichar i_tolower(unichar c)
 {
 	if (term_type == TERM_TYPE_UTF8)
 		return g_unichar_tolower(c);
-	return (c >= 0 && c <= 255) ? tolower(c) : c;
+	return c <= 255 ? tolower(c) : c;
 }
 
 static int i_isalnum(unichar c)
 {
 	if (term_type == TERM_TYPE_UTF8)
 		return (g_unichar_isalnum(c) || mk_wcwidth(c) == 0);
-	return (c >= 0 && c <= 255) ? isalnum(c) : 0;
+	return c <= 255 ? isalnum(c) : 0;
 }
 
 GUI_ENTRY_REC *active_entry;

From 2127fd362e240a9fed09dff9044fe5c477fc2bf8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexander=20F=C3=A6r=C3=B8y?= 
Date: Sat, 3 Oct 2015 19:07:08 +0200
Subject: [PATCH 0189/1650] Add -Wall and -Werror as CFLAGS to make.

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index c8bbb6d8..46f58766 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,5 +22,5 @@ install: true
 script:
     - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build
     - cat config.log
-    - make
+    - make CFLAGS="-Wall -Werror"
     - make install

From 0140e7c6b23ff1490965b080a7882b2508677d55 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Sun, 4 Oct 2015 11:56:54 +0200
Subject: [PATCH 0190/1650] Fix the indentation.

---
 src/fe-text/term-terminfo.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 6d289cfc..27be904e 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -537,14 +537,14 @@ int term_addstr(TERM_WINDOW *window, const char *str)
 
 	ptr = str;
 
-	if (term_type != TERM_TYPE_BIG5) {
-	    while (*ptr != '\0') {
-		tmp = g_utf8_get_char(ptr);
-		len += unichar_isprint(tmp) ? mk_wcwidth(tmp) : 1;
-		ptr = g_utf8_next_char(ptr);
-	    }
+	if (term_type == TERM_TYPE_UTF8) {
+		while (*ptr != '\0') {
+			tmp = g_utf8_get_char(ptr);
+			len += unichar_isprint(tmp) ? mk_wcwidth(tmp) : 1;
+			ptr = g_utf8_next_char(ptr);
+		}
 	} else
-	    len = raw_len;
+		len = raw_len;
 
         term_printed_text(len);
 

From 58a166484ad7eab33c1ad72b64016e5aacebfaf5 Mon Sep 17 00:00:00 2001
From: dequis 
Date: Tue, 6 Oct 2015 04:51:16 -0300
Subject: [PATCH 0191/1650] Add xterm's keypad enter, meta-O-M to "key return"
 bindings

From the 'kent' terminfo entry. Also applies to putty.

Fixes #327
---
 src/fe-text/gui-readline.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index ec61e317..dc7185e7 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -1020,6 +1020,8 @@ void gui_readline_init(void)
 	key_bind("key", NULL, "meta2-5F", "cend", (SIGNAL_FUNC) key_combo);
 	key_bind("key", NULL, "meta2-1;5F", "cend", (SIGNAL_FUNC) key_combo);
 
+	key_bind("key", NULL, "meta-O-M", "return", (SIGNAL_FUNC) key_combo);
+
 	/* cursor movement */
 	key_bind("backward_character", "Move the cursor a character backward", "left", NULL, (SIGNAL_FUNC) key_backward_character);
 	key_bind("forward_character", "Move the cursor a character forward", "right", NULL, (SIGNAL_FUNC) key_forward_character);

From f540ec9de1bb35b226e3c97e763238072fe295dd Mon Sep 17 00:00:00 2001
From: dequis 
Date: Thu, 8 Oct 2015 00:06:17 -0300
Subject: [PATCH 0192/1650] Fix /reconnect RECON-1 saying "Reconnection tag 1
 not found"

Turns out it was fixing the wrong string, and trying to do
atoi("RECON-1") instead of atoi("1").

"/reconnect 1" worked, but "/reconnect RECON-1" gave that confusing
error message.
---
 src/core/servers-reconnect.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c
index ae97ecd2..f419035b 100644
--- a/src/core/servers-reconnect.c
+++ b/src/core/servers-reconnect.c
@@ -420,8 +420,8 @@ static void cmd_reconnect(const char *data, SERVER_REC *server)
 			cmd_param_error(CMDERR_NOT_CONNECTED);
                 rec = reconnects->data;
 	} else {
-		if (g_ascii_strncasecmp(data, "RECON-", 6) == 0)
-			data += 6;
+		if (g_ascii_strncasecmp(tag, "RECON-", 6) == 0)
+			tag += 6;
 
 		tagnum = atoi(tag);
 		rec = tagnum <= 0 ? NULL : reconnect_find_tag(tagnum);

From ed28483e7509f0a7a75716f2651f603824fd9817 Mon Sep 17 00:00:00 2001
From: dequis 
Date: Fri, 23 Oct 2015 04:25:57 -0300
Subject: [PATCH 0193/1650] Fix invalid reads in strsplit_len when splitting on
 spaces

The symptom for this one is randomly getting lines split before the last
word, even if there's no need for splitting. Also, this function is only
reached if recode is on, and iconv failed (for example, due to an
incorrect source charset). Thanks to vague for finding this and
providing valgrind logs.

The loop that looks for spaces tried to read backwards from the end of
the current line, with the end being determined by len. Assuming
strsplit_len() with len=400, this meant accessing str[399] in the first
iteration. For strings that don't need splitting, this means an invalid
read always.

If that invalid read happens to hit garbage that has a space character,
(len - offset) points after the end of string, which isn't a problem for
g_strndup() since it stops at the first null, and no splitting happens.
If the garbage doesn't have any spaces, it splits by the last word.

This commit avoids that loop entirely if (remaining_len > len). It also
changes the way it iterates over the string to be much less confusing.
---
 src/core/misc.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/core/misc.c b/src/core/misc.c
index 88c27255..e209efa1 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -995,25 +995,29 @@ char **strsplit_len(const char *str, int len, gboolean onspace)
 {
 	char **ret = g_new(char *, 1);
 	int n;
-	int offset;
+	int split_offset = 0;
+	size_t remaining_len = strlen(str);
 
-	for (n = 0; *str != '\0'; n++, str += MIN(len - offset, strlen(str))) {
-		offset = 0;
-		if (onspace) {
+	for (n = 0; *str != '\0'; n++) {
+		split_offset = MIN(len, remaining_len);
+		if (onspace && remaining_len > len) {
 			/*
 			 * Try to find a space to split on and leave
 			 * the space on the previous line.
 			 */
 			int i;
-			for (i = 0; i < len; i++) {
-				if (str[len-1-i] == ' ') {
-					offset = i;
+			for (i = len - 1; i > 0; i--) {
+				if (str[i] == ' ') {
+					split_offset = i;
 					break;
 				}
 			}
 		}
-		ret[n] = g_strndup(str, len - offset);
+		ret[n] = g_strndup(str, split_offset);
 		ret = g_renew(char *, ret, n + 2);
+
+		str += split_offset;
+		remaining_len -= split_offset;
 	}
 	ret[n] = NULL;
 

From 06bf25bfbaaf33772e36317dba28ce5b6a301616 Mon Sep 17 00:00:00 2001
From: Rodrigo Rebello 
Date: Wed, 28 Oct 2015 13:38:21 -0200
Subject: [PATCH 0194/1650] Fix quote around macro argument

In m4/curses.m4, line 134, the 5th argument passed to AC_NCURSES was
surrounded by '"' instead of '[' and ']'. Because of that, the expansion
of AC_NCURSES in that case would produce the following line inside the
configure script (note the repeated double quotes):

  screen_manager=""ncurses on $withval/include""

That would cause the following error when configure was executed with
the "--with-ncurses=dir" argument:

  ./configure: line 13468: on: command not found

Although in the case above the error doesn't actually influence the
build process ('screen_manager' isn't used anywhere in the script),
trying to execute 'on' might be harmful if it corresponded to an
existing command in the user's environment.
---
 m4/curses.m4 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/m4/curses.m4 b/m4/curses.m4
index 82b110fe..41c0e6c8 100644
--- a/m4/curses.m4
+++ b/m4/curses.m4
@@ -131,7 +131,7 @@ AC_DEFUN([AC_CHECK_CURSES],[
 	  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")
+		AC_NCURSES($withval/include, ncurses.h, -L$withval/lib -lncurses, -I$withval/include, [ncurses on $withval/include])
 	  fi
 	)
 

From 8094e87cdf78bd864ffb37351ff4853cb127d8d1 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Wed, 28 Oct 2015 21:56:35 +0100
Subject: [PATCH 0195/1650] Preserve the sasl_ options across reconnects.

---
 src/irc/core/irc-servers-reconnect.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/irc/core/irc-servers-reconnect.c b/src/irc/core/irc-servers-reconnect.c
index b0aad26f..ca61492d 100644
--- a/src/irc/core/irc-servers-reconnect.c
+++ b/src/irc/core/irc-servers-reconnect.c
@@ -48,6 +48,9 @@ static void sig_server_connect_copy(SERVER_CONNECT_REC **dest,
 	rec->max_whois = src->max_whois;
 	rec->usermode = g_strdup(src->usermode);
 	rec->alternate_nick = g_strdup(src->alternate_nick);
+	rec->sasl_mechanism = src->sasl_mechanism;
+	rec->sasl_username = src->sasl_username;
+	rec->sasl_password = src->sasl_password;
 	*dest = (SERVER_CONNECT_REC *) rec;
 }
 

From 3c95f6aae9826c10a50c4a0f12c16fca6038410c Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt" 
Date: Mon, 2 Nov 2015 08:00:52 -0500
Subject: [PATCH 0196/1650] 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 8736c12fc95ca977f4fc4a947c760bac651cd3af Mon Sep 17 00:00:00 2001
From: dequis 
Date: Mon, 9 Nov 2015 06:33:08 -0300
Subject: [PATCH 0197/1650] strsplit_len: use strlen() directly instead of a
 remaining_len variable

---
 src/core/misc.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/core/misc.c b/src/core/misc.c
index e209efa1..4e8322fa 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -996,11 +996,10 @@ char **strsplit_len(const char *str, int len, gboolean onspace)
 	char **ret = g_new(char *, 1);
 	int n;
 	int split_offset = 0;
-	size_t remaining_len = strlen(str);
 
 	for (n = 0; *str != '\0'; n++) {
-		split_offset = MIN(len, remaining_len);
-		if (onspace && remaining_len > len) {
+		split_offset = MIN(len, strlen(str));
+		if (onspace && strlen(str) > len) {
 			/*
 			 * Try to find a space to split on and leave
 			 * the space on the previous line.
@@ -1017,7 +1016,6 @@ char **strsplit_len(const char *str, int len, gboolean onspace)
 		ret = g_renew(char *, ret, n + 2);
 
 		str += split_offset;
-		remaining_len -= split_offset;
 	}
 	ret[n] = NULL;
 

From b054ade4b90a05d778a64c63c0c834a126884aaa Mon Sep 17 00:00:00 2001
From: dequis 
Date: Mon, 9 Nov 2015 06:46:40 -0300
Subject: [PATCH 0198/1650] strsplit_len: make it look more like the original
 version

---
 src/core/misc.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/src/core/misc.c b/src/core/misc.c
index 4e8322fa..490b5a8f 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -995,10 +995,10 @@ char **strsplit_len(const char *str, int len, gboolean onspace)
 {
 	char **ret = g_new(char *, 1);
 	int n;
-	int split_offset = 0;
+	int offset;
 
-	for (n = 0; *str != '\0'; n++) {
-		split_offset = MIN(len, strlen(str));
+	for (n = 0; *str != '\0'; n++, str += offset) {
+		offset = MIN(len, strlen(str));
 		if (onspace && strlen(str) > len) {
 			/*
 			 * Try to find a space to split on and leave
@@ -1007,15 +1007,13 @@ char **strsplit_len(const char *str, int len, gboolean onspace)
 			int i;
 			for (i = len - 1; i > 0; i--) {
 				if (str[i] == ' ') {
-					split_offset = i;
+					offset = i;
 					break;
 				}
 			}
 		}
-		ret[n] = g_strndup(str, split_offset);
+		ret[n] = g_strndup(str, offset);
 		ret = g_renew(char *, ret, n + 2);
-
-		str += split_offset;
 	}
 	ret[n] = NULL;
 

From 1006fee8027936c68e0f0b2f8dae766ad090764a Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Mon, 9 Nov 2015 17:32:51 +0100
Subject: [PATCH 0199/1650] Add an option to strip trailing whitespace when
 parsing commands

---
 src/core/commands.c | 5 +++++
 src/core/commands.h | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/src/core/commands.c b/src/core/commands.c
index 9e451bc8..0fb373c7 100644
--- a/src/core/commands.c
+++ b/src/core/commands.c
@@ -748,6 +748,11 @@ int cmd_get_params(const char *data, gpointer *free_me, int count, ...)
 			if (cnt == 0 && count & PARAM_FLAG_GETREST) {
 				/* get rest */
 				arg = datad;
+
+				/* strip the trailing whitespace */
+				if (count & PARAM_FLAG_STRIP_TRAILING_WS) {
+					arg = g_strchomp (arg);
+				}
 			} else {
 				arg = (count & PARAM_FLAG_NOQUOTES) ?
 					cmd_get_param(&datad) :
diff --git a/src/core/commands.h b/src/core/commands.h
index d65185e5..72105ad3 100644
--- a/src/core/commands.h
+++ b/src/core/commands.h
@@ -152,6 +152,8 @@ int command_have_option(const char *cmd, const char *option);
 #define PARAM_FLAG_OPTCHAN 0x00010000
 /* optional channel in first argument, but don't treat "*" as current channel */
 #define PARAM_FLAG_OPTCHAN_NAME (0x00020000|PARAM_FLAG_OPTCHAN)
+/* strip the trailing whitespace */
+#define PARAM_FLAG_STRIP_TRAILING_WS 0x00040000
 
 char *cmd_get_param(char **data);
 char *cmd_get_quoted_param(char **data);

From 3d9b9d473fdd2ec6af367df27cfc26a90a3f4375 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Mon, 9 Nov 2015 18:39:13 +0100
Subject: [PATCH 0200/1650] Strip the trailing whitespace from /join commands.

Fixes #99 for great good.
---
 src/core/commands.c              | 2 +-
 src/fe-common/core/fe-channels.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/core/commands.c b/src/core/commands.c
index 0fb373c7..88d1208c 100644
--- a/src/core/commands.c
+++ b/src/core/commands.c
@@ -751,7 +751,7 @@ int cmd_get_params(const char *data, gpointer *free_me, int count, ...)
 
 				/* strip the trailing whitespace */
 				if (count & PARAM_FLAG_STRIP_TRAILING_WS) {
-					arg = g_strchomp (arg);
+					arg = g_strchomp(arg);
 				}
 			} else {
 				arg = (count & PARAM_FLAG_NOQUOTES) ?
diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c
index a171596d..046d641a 100644
--- a/src/fe-common/core/fe-channels.c
+++ b/src/fe-common/core/fe-channels.c
@@ -122,7 +122,8 @@ static void cmd_join(const char *data, SERVER_REC *server)
 	void *free_arg;
 
 	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
-			    PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
+			    PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST |
+			    PARAM_FLAG_STRIP_TRAILING_WS,
 			    "join", &optlist, &pdata))
 		return;
 

From d4676c985553dc957e863e814097beba9bcc279e Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Mon, 9 Nov 2015 23:02:41 +0100
Subject: [PATCH 0201/1650] Use the PARAM_FLAG_STRIP_TRAILING_WS flag wherever
 possible.

---
 src/fe-common/core/completion.c      |  2 +-
 src/fe-common/core/fe-ignore.c       |  3 ++-
 src/fe-common/core/fe-log.c          |  5 +++--
 src/fe-common/core/fe-settings.c     |  5 +++--
 src/fe-common/irc/fe-irc-commands.c  |  4 ++--
 src/irc/core/bans.c                  | 12 ++++++------
 src/irc/core/irc-commands.c          | 12 ++++++++----
 src/irc/core/modes.c                 |  4 ++--
 src/irc/dcc/dcc-send.c               |  4 ++--
 src/irc/dcc/dcc.c                    |  4 ++--
 src/irc/notifylist/notify-commands.c |  3 ++-
 11 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c
index 4461de92..a4715d23 100644
--- a/src/fe-common/core/completion.c
+++ b/src/fe-common/core/completion.c
@@ -757,7 +757,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_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
 			    "completion", &optlist, &key, &value))
 		return;
 
diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c
index 533cda31..d2f9de27 100644
--- a/src/fe-common/core/fe-ignore.c
+++ b/src/fe-common/core/fe-ignore.c
@@ -127,7 +127,8 @@ static void cmd_ignore(const char *data)
 		return;
 	}
 
-	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
+	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | 
+			    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
 			    "ignore", &optlist, &mask, &levels))
 		return;
 
diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c
index a39623d2..476abaab 100644
--- a/src/fe-common/core/fe-log.c
+++ b/src/fe-common/core/fe-log.c
@@ -87,8 +87,9 @@ static void cmd_log_open(const char *data)
 	int level;
 
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST |
-			    PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_OPTIONS,
-			    "log open", &optlist, &fname, &levels))
+			    PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_OPTIONS |
+			    PARAM_FLAG_STRIP_TRAILING_WS, "log open", &optlist, 
+			    &fname, &levels))
 		return;
 	if (*fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
 
diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index 2627989d..3bb43bf7 100644
--- a/src/fe-common/core/fe-settings.c
+++ b/src/fe-common/core/fe-settings.c
@@ -108,7 +108,8 @@ static void cmd_set(char *data)
 	int clear, set_default;
 	SETTINGS_REC *rec;
 
-	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_OPTIONS,
+	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST |
+			    PARAM_FLAG_OPTIONS | PARAM_FLAG_STRIP_TRAILING_WS,
 			    "set", &optlist, &key, &value))
 		return;
 
@@ -182,7 +183,7 @@ static void cmd_toggle(const char *data)
 	void *free_arg;
 	int type;
 
-	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &key, &value))
+	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, &key, &value))
 		return;
 
 	if (*key == '\0')
diff --git a/src/fe-common/irc/fe-irc-commands.c b/src/fe-common/irc/fe-irc-commands.c
index a23facbd..11a911d2 100644
--- a/src/fe-common/irc/fe-irc-commands.c
+++ b/src/fe-common/irc/fe-irc-commands.c
@@ -246,8 +246,8 @@ static void cmd_ban(const char *data, IRC_SERVER_REC *server,
 
         CMD_IRC_SERVER(server);
 
-	if (!cmd_get_params(data, &free_arg, 2 |
-			    PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
+	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | 
+			    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
 			    item, &channel, &nicks))
 		return;
 
diff --git a/src/irc/core/bans.c b/src/irc/core/bans.c
index 68dd45c0..198fdc4a 100644
--- a/src/irc/core/bans.c
+++ b/src/irc/core/bans.c
@@ -184,8 +184,8 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server,
 	if (server == NULL || !server->connected || !IS_IRC_SERVER(server))
 		cmd_return_error(CMDERR_NOT_CONNECTED);
 
-	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
-			    item, &channel, &nicks)) return;
+	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST |
+			    PARAM_FLAG_STRIP_TRAILING_WS, item, &channel, &nicks)) return;
 	if (!server_ischannel(SERVER(server), channel)) cmd_param_error(CMDERR_NOT_JOINED);
 	if (*nicks == '\0') {
 		if (g_strcmp0(data, "*") != 0)
@@ -262,8 +262,8 @@ static void cmd_ban(const char *data, IRC_SERVER_REC *server, void *item)
 
         CMD_IRC_SERVER(server);
 
-	if (!cmd_get_params(data, &free_arg, 1 |
-			    PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
+	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | 
+			    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
 			    "ban", &optlist, &ban))
 		return;
 
@@ -297,8 +297,8 @@ static void cmd_unban(const char *data, IRC_SERVER_REC *server, void *item)
 
         CMD_IRC_SERVER(server);
 
-	if (!cmd_get_params(data, &free_arg, 1 |
-			    PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
+	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | 
+			    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
 			    "unban", &optlist, &ban))
 		return;
 
diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c
index 47644753..3cc105ba 100644
--- a/src/irc/core/irc-commands.c
+++ b/src/irc/core/irc-commands.c
@@ -267,7 +267,8 @@ static void cmd_list(const char *data, IRC_SERVER_REC *server,
         CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
-			    PARAM_FLAG_GETREST, "list", &optlist, &str))
+			    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, 
+			    "list", &optlist, &str))
 		return;
 
 	if (*str == '\0' && g_hash_table_lookup(optlist, "yes") == NULL &&
@@ -288,7 +289,8 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server,
 
 	CMD_IRC_SERVER(server);
 
-	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channel, &rest))
+	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | 
+			    PARAM_FLAG_STRIP_TRAILING_WS, &channel, &rest))
 		return;
 
 	if (g_strcmp0(channel, "*") == 0 || *channel == '\0') {
@@ -320,7 +322,8 @@ static void cmd_names(const char *data, IRC_SERVER_REC *server,
         CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
-			    PARAM_FLAG_GETREST, "names", &optlist, &channel))
+			    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
+			    "names", &optlist, &channel))
 		return;
 
 	if (g_strcmp0(channel, "*") == 0 || *channel == '\0') {
@@ -501,7 +504,8 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
 
         CMD_IRC_SERVER(server);
 
-	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nicks, &rest))
+	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
+			    &nicks, &rest))
 		return;
 	if (*nicks == '\0') nicks = server->nick;
 
diff --git a/src/irc/core/modes.c b/src/irc/core/modes.c
index 32a0c169..207461cc 100644
--- a/src/irc/core/modes.c
+++ b/src/irc/core/modes.c
@@ -835,10 +835,10 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server,
 
 	if (*data == '+' || *data == '-') {
 		target = "*";
-		if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_GETREST, &mode))
+		if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, &mode))
 			return;
 	} else {
-		if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &mode))
+		if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, &target, &mode))
 			return;
 	}
 
diff --git a/src/irc/dcc/dcc-send.c b/src/irc/dcc/dcc-send.c
index 2ce84f18..ca29b9b9 100644
--- a/src/irc/dcc/dcc-send.c
+++ b/src/irc/dcc/dcc-send.c
@@ -174,8 +174,8 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server,
 	int queue, mode, passive;
 
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS |
-			    PARAM_FLAG_GETREST, "dcc send",
-			    &optlist, &nick, &fileargs))
+			    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, 
+			    "dcc send", &optlist, &nick, &fileargs))
 		return;
 
 	chat = item_get_dcc(item);
diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c
index 17f6c477..7f35585e 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,
-			    &typestr, &nick, &arg))
+	if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST |
+			    PARAM_FLAG_STRIP_TRAILING_WS, &typestr, &nick, &arg))
 		return;
 
 	if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
diff --git a/src/irc/notifylist/notify-commands.c b/src/irc/notifylist/notify-commands.c
index 67076106..0d4fd4f2 100644
--- a/src/irc/notifylist/notify-commands.c
+++ b/src/irc/notifylist/notify-commands.c
@@ -36,7 +36,8 @@ static void cmd_notify(gchar *data)
 
 	g_return_if_fail(data != NULL);
 
-	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
+	if (!cmd_get_params(data, &free_arg,
+			    2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
 			    "notify", &optlist, &mask, &ircnets))
 		return;
 	if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);

From b333d103641b48b77ab76c6d31b1f3788192268f Mon Sep 17 00:00:00 2001
From: Jari Matilainen 
Date: Mon, 9 Nov 2015 23:06:56 +0100
Subject: [PATCH 0202/1650] /hilight list print output with enabled flags,
 except when -word and -nick are used

---
 src/fe-common/core/hilight-text.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index 87c5d467..9822de1e 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -484,10 +484,14 @@ static void hilight_print(int index, HILIGHT_REC *rec)
 	GString *options;
 
 	options = g_string_new(NULL);
-	if (!rec->nick || !rec->word) {
-		if (rec->nick) g_string_append(options, "-nick ");
-		if (rec->word) g_string_append(options, "-word ");
-	}
+
+	if (rec->nick && rec->word) { /* default case, no option */ }
+	else if (rec->nick)
+		g_string_append(options, "-nick ");
+	else if (rec->word)
+		g_string_append(options, "-word ");
+	else
+		g_string_append(options, "-line ");
 
 	if (rec->nickmask) g_string_append(options, "-mask ");
 	if (rec->fullword) g_string_append(options, "-full ");

From 1199ecc62f137eedb388b3dbd9b003cf1a8280f7 Mon Sep 17 00:00:00 2001
From: "Todd A. Pratt" 
Date: Fri, 13 Nov 2015 13:42:28 -0500
Subject: [PATCH 0203/1650] 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 0204/1650] 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 0205/1650] 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 0206/1650] 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 0207/1650] 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 d7ef9c590fa679403da103f8e89042aad6abb919 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Thu, 19 Nov 2015 15:31:32 +0100
Subject: [PATCH 0208/1650] Correctly alias 'channel' to '#channel'

Use the same approach used in 'irc_channels_join'.
Remove 'irc_nick_strip' since it was unused.
---
 src/irc/core/irc-channels.c | 17 +++++++++++++++--
 src/irc/core/irc-nicklist.c | 24 ------------------------
 src/irc/core/irc-nicklist.h |  3 ---
 3 files changed, 15 insertions(+), 29 deletions(-)

diff --git a/src/irc/core/irc-channels.c b/src/irc/core/irc-channels.c
index 682be4c2..e775f530 100644
--- a/src/irc/core/irc-channels.c
+++ b/src/irc/core/irc-channels.c
@@ -174,6 +174,13 @@ static CHANNEL_REC *irc_channel_find_server(SERVER_REC *server,
 					    const char *channel)
 {
 	GSList *tmp;
+	char *fmt_channel;
+
+	/* if 'channel' has no leading # this lookup is going to fail, add a
+	 * octothorpe in front of it to handle this case. */
+	fmt_channel = server_ischannel(SERVER(server), channel) ?
+	    g_strdup(channel) :
+	    g_strdup_printf("#%s", channel);
 
 	for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
 		CHANNEL_REC *rec = tmp->data;
@@ -182,13 +189,19 @@ static CHANNEL_REC *irc_channel_find_server(SERVER_REC *server,
                         continue;
 
 		/* check both !ABCDEchannel and !channel */
-		if (IRC_SERVER(server)->nick_comp_func(channel, rec->name) == 0)
+		if (IRC_SERVER(server)->nick_comp_func(fmt_channel, rec->name) == 0) {
+			g_free(fmt_channel);
 			return rec;
+		}
 
-		if (IRC_SERVER(server)->nick_comp_func(channel, rec->visible_name) == 0)
+		if (IRC_SERVER(server)->nick_comp_func(fmt_channel, rec->visible_name) == 0) {
+			g_free(fmt_channel);
 			return rec;
+		}
 	}
 
+	g_free(fmt_channel);
+
 	return NULL;
 }
 
diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c
index 667016aa..bcb9d1f6 100644
--- a/src/irc/core/irc-nicklist.c
+++ b/src/irc/core/irc-nicklist.c
@@ -55,30 +55,6 @@ NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick,
 	return rec;
 }
 
-#define isnickchar(a) \
-	(i_isalnum(a) || (a) == '`' || (a) == '-' || (a) == '_' || \
-	(a) == '[' || (a) == ']' || (a) == '{' || (a) == '}' || \
-	(a) == '|' || (a) == '\\' || (a) == '^')
-
-/* Remove all "extra" characters from `nick'. Like _nick_ -> nick */
-char *irc_nick_strip(const char *nick)
-{
-	char *stripped, *spos;
-
-	g_return_val_if_fail(nick != NULL, NULL);
-
-	spos = stripped = g_strdup(nick);
-	while (isnickchar(*nick)) {
-		if (i_isalnum(*nick))
-			*spos++ = *nick;
-		nick++;
-	}
-	if ((unsigned char) *nick >= 128)
-		*spos++ = *nick; /* just add it so that nicks won't match.. */
-	*spos = '\0';
-	return stripped;
-}
-
 int irc_nickcmp_rfc1459(const char *m, const char *n)
 {
 	while (*m != '\0' && *n != '\0') {
diff --git a/src/irc/core/irc-nicklist.h b/src/irc/core/irc-nicklist.h
index 7302556b..2ae17d2c 100644
--- a/src/irc/core/irc-nicklist.h
+++ b/src/irc/core/irc-nicklist.h
@@ -8,9 +8,6 @@ NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick,
 			      int op, int halfop, int voice, int send_massjoin,
 			      const char *prefixes);
 
-/* Remove all "extra" characters from `nick'. Like _nick_ -> nick */
-char *irc_nick_strip(const char *nick);
-
 int irc_nickcmp_rfc1459(const char *, const char *);
 int irc_nickcmp_ascii(const char *, const char *);
 

From 8701cbc972955ba7522390988e3c0e0c62770fa4 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Sun, 22 Nov 2015 16:57:45 +0100
Subject: [PATCH 0209/1650] Let ignore_check do its work when server is NULL

A NULL-check has been added to the ignore_match_server macro, making the
function safe from a pointer perspective.
Fixes #193 in the meanwhile.
---
 src/core/ignore.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/core/ignore.c b/src/core/ignore.c
index e70b741b..fd3c8a38 100644
--- a/src/core/ignore.c
+++ b/src/core/ignore.c
@@ -97,8 +97,8 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text)
 		match_wildcards((rec)->mask, nick)))
 
 #define ignore_match_server(rec, server) \
-	((rec)->servertag == NULL || \
-	g_ascii_strcasecmp((server)->tag, (rec)->servertag) == 0)
+	((rec)->servertag == NULL || ((server) != NULL && \
+		g_ascii_strcasecmp((server)->tag, (rec)->servertag) == 0))
 
 #define ignore_match_channel(rec, channel) \
 	((rec)->channels == NULL || ((channel) != NULL && \
@@ -135,7 +135,6 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host,
         char *nickmask;
         int len, best_mask, best_match, best_patt;
 
-	g_return_val_if_fail(server != NULL, 0);
         if (nick == NULL) nick = "";
 
 	chanrec = server == NULL || channel == NULL ? NULL :

From 011eda7d9e755d1df82b678c05c0cb9b1aaa1e29 Mon Sep 17 00:00:00 2001
From: Fabian Kurz 
Date: Sun, 22 Nov 2015 21:24:05 +0100
Subject: [PATCH 0210/1650] Correct a wrong use of the 'paste_buffer' variable

The function "static void paste_buffer_join_lines(GArray *buf)" in
"src/fe-text/gui-readline.c" is supposed to join lines from the GArray
pointed to by *buf under certain circumstances.

In the code of the function "buf" is actually used for getting the length
of the GArray, but to get a pointer to the data, "paste_buffer->data" is
used; paste_buffer is defined in the scope of the whole file.

This delivers the desired result, because this function is only called
once, with "paste_buffer" as the argument. If paste_buffer_join_lines()
will ever be used with a different argument, it will fail.
---
 src/fe-text/gui-readline.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index dc7185e7..ecf116fe 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -177,7 +177,7 @@ static void paste_buffer_join_lines(GArray *buf)
 	if (buf->len == 0)
 		return;
 
-	arr = (unichar *) paste_buffer->data;
+	arr = (unichar *)buf->data;
 
 	/* first line */
 	if (IS_WHITE(arr[0]))

From 50fae4212ec5fbb9931093b1c31bbeda97ddfbb3 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Sun, 22 Nov 2015 21:33:44 +0100
Subject: [PATCH 0211/1650] Use 'isblank()' instead of a custom macro

---
 src/fe-text/gui-readline.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index ecf116fe..a8f3ba99 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -147,7 +147,6 @@ static void window_next_page(void)
 
 static void paste_buffer_join_lines(GArray *buf)
 {
-#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
 	unsigned int i, count, indent, line_len;
 	unichar *arr, *dest, *last_lf_pos;
 	int last_lf;
@@ -180,12 +179,12 @@ static void paste_buffer_join_lines(GArray *buf)
 	arr = (unichar *)buf->data;
 
 	/* first line */
-	if (IS_WHITE(arr[0]))
+	if (isblank(arr[0]))
 		return;
 
 	/* find the first beginning of indented line */
 	for (i = 1; i < buf->len; i++) {
-		if (arr[i-1] == '\n' && IS_WHITE(arr[i]))
+		if (arr[i-1] == '\n' && isblank(arr[i]))
 			break;
 	}
 	if (i == buf->len)
@@ -193,7 +192,7 @@ static void paste_buffer_join_lines(GArray *buf)
 
 	/* get how much indentation we have.. */
 	for (indent = 0; i < buf->len; i++, indent++) {
-		if (!IS_WHITE(arr[i]))
+		if (!isblank(arr[i]))
 			break;
 	}
 	if (i == buf->len)
@@ -203,7 +202,7 @@ static void paste_buffer_join_lines(GArray *buf)
 	count = indent; last_lf = TRUE;
 	for (; i < buf->len; i++) {
 		if (last_lf) {
-			if (IS_WHITE(arr[i]))
+			if (isblank(arr[i]))
 				count++;
 			else {
 				last_lf = FALSE;
@@ -220,11 +219,11 @@ static void paste_buffer_join_lines(GArray *buf)
 	   get longer than 400 chars */
 	dest = arr; last_lf = TRUE; last_lf_pos = NULL; line_len = 0;
 	for (i = 0; i < buf->len; i++) {
-		if (last_lf && IS_WHITE(arr[i])) {
+		if (last_lf && isblank(arr[i])) {
 			/* whitespace, ignore */
 		} else if (arr[i] == '\n') {
 			if (!last_lf && i+1 != buf->len &&
-			    IS_WHITE(arr[i+1])) {
+			    isblank(arr[i+1])) {
 				last_lf_pos = dest;
 				*dest++ = ' ';
 			} else {

From 0171b1a6343434477845ac5365e5ee20ceef7904 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Sun, 22 Nov 2015 21:59:28 +0100
Subject: [PATCH 0212/1650] Use the expanded filename when picking the awaylog

This fixes a long-standing bug where 'fname' was being feed to cat
instead of 'real_fname', causing it to quit with a 'No such file or directory'
error.

FS#377
---
 src/fe-common/core/fe-log.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c
index 476abaab..f2c4c014 100644
--- a/src/fe-common/core/fe-log.c
+++ b/src/fe-common/core/fe-log.c
@@ -617,7 +617,7 @@ static void sig_window_item_remove(WINDOW_REC *window, WI_ITEM_REC *item)
 static void sig_log_locked(LOG_REC *log)
 {
 	printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
-		    TXT_LOG_LOCKED, log->fname);
+		    TXT_LOG_LOCKED, log->real_fname);
 }
 
 static void sig_log_create_failed(LOG_REC *log)
@@ -657,11 +657,11 @@ static void sig_awaylog_show(LOG_REC *log, gpointer pmsgs, gpointer pfilepos)
 	filepos = GPOINTER_TO_INT(pfilepos);
 
 	if (msgs == 0)
-		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_NO_AWAY_MSGS, log->fname);
+		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_NO_AWAY_MSGS, log->real_fname);
 	else {
-		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_AWAY_MSGS, log->fname, msgs);
+		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_LOG_AWAY_MSGS, log->real_fname, msgs);
 
-                str = g_strdup_printf("\"%s\" %d", log->fname, filepos);
+                str = g_strdup_printf("\"%s\" %d", log->real_fname, filepos);
 		signal_emit("command cat", 1, str);
 		g_free(str);
 	}

From 877ff075bde3dee9da01f53e1afcf18be7ddf703 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Tue, 24 Nov 2015 00:30:12 +0100
Subject: [PATCH 0213/1650] stop cap_sasl

---
 src/perl/irssi-core.pl | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/perl/irssi-core.pl b/src/perl/irssi-core.pl
index 38265a80..46066a38 100644
--- a/src/perl/irssi-core.pl
+++ b/src/perl/irssi-core.pl
@@ -47,4 +47,8 @@ sub eval_file {
   $data = qq{\n#line 1 "$filename"\n$data};
 
   eval_data($data, $id);
+
+  if (exists ${"Irssi::Script::${id}::"}{IRSSI} && ${"Irssi::Script::${id}::"}{IRSSI}{name} =~ /cap.sasl/ && ${"Irssi::Script::${id}::VERSION"} < 2) {
+    die "cap_sasl has been unloaded from Irssi ".Irssi::version()." because it conflicts with the built-in SASL support. See /help network for configuring SASL or read the ChangeLog for more information.";
+  }
 }

From a941329b4140b436d0bd5316a29d8be47019d1ea Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Tue, 24 Nov 2015 00:40:19 +0100
Subject: [PATCH 0214/1650] fix nick class hierarchy

---
 src/perl/common/Irssi.pm | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/perl/common/Irssi.pm b/src/perl/common/Irssi.pm
index a9f93bf0..3ff02d5a 100644
--- a/src/perl/common/Irssi.pm
+++ b/src/perl/common/Irssi.pm
@@ -159,6 +159,7 @@ if (!in_irssi()) {
 
   @Irssi::Channel::ISA = qw(Irssi::Windowitem);
   @Irssi::Query::ISA = qw(Irssi::Windowitem);
+  @Irssi::Nick::ISA = qw();
 
   Irssi::init();
 

From 11ad4da0e33f565e83008045fe2532bb713f1f6b Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Wed, 25 Nov 2015 12:16:42 +0100
Subject: [PATCH 0215/1650] more perl inheritance warning fixes

---
 src/perl/common/Irssi.pm | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/perl/common/Irssi.pm b/src/perl/common/Irssi.pm
index 3ff02d5a..e2d9f963 100644
--- a/src/perl/common/Irssi.pm
+++ b/src/perl/common/Irssi.pm
@@ -159,6 +159,7 @@ if (!in_irssi()) {
 
   @Irssi::Channel::ISA = qw(Irssi::Windowitem);
   @Irssi::Query::ISA = qw(Irssi::Windowitem);
+  @Irssi::Chatnet::ISA = qw();
   @Irssi::Nick::ISA = qw();
 
   Irssi::init();

From 6ac6fcec469227971e7856201c27de09e1773ae4 Mon Sep 17 00:00:00 2001
From: Will Song 
Date: Wed, 25 Nov 2015 11:53:48 -0600
Subject: [PATCH 0216/1650] ignore MYMETA.* generated by scripts in project
 root

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 0b15f43e..945b6cf6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,7 @@ ltversion.m4
 lt~obsolete.m4
 pm_to_blib
 stamp-h1
+MYMETA.*
 
 docs/help/Makefile.am
 docs/help/[a-z]*

From c52e6ebc992a317bfa3c1a67b8931e2e6cc40215 Mon Sep 17 00:00:00 2001
From: Will Song 
Date: Wed, 25 Nov 2015 11:55:18 -0600
Subject: [PATCH 0217/1650] change ./configure to ./autogen.sh because
 ./configure does not exist in a fresh clone of the repository

---
 INSTALL | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/INSTALL b/INSTALL
index a83a6c76..fdf4200d 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,7 +11,7 @@ To compile irssi you need:
 
 For most people, this should work just fine:
 
- ./configure
+ ./autogen.sh
  make
  su
  make install     (not _really_ required except for perl support)

From 54153e6d887545b5f2b46580ce1f7eba2f7c702b Mon Sep 17 00:00:00 2001
From: Will Song 
Date: Wed, 25 Nov 2015 12:25:55 -0600
Subject: [PATCH 0218/1650] revise INSTALL to be more clear regarding which
 script to use

---
 INSTALL | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/INSTALL b/INSTALL
index fdf4200d..234c6cf6 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,7 +11,8 @@ To compile irssi you need:
 
 For most people, this should work just fine:
 
- ./autogen.sh
+ ./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)

From 82ce1de5b004d27b8a742a72065feebf6d96f3ae Mon Sep 17 00:00:00 2001
From: dequis 
Date: Thu, 26 Nov 2015 19:50:58 -0300
Subject: [PATCH 0219/1650] irc-cap: Don't send a space at the beginning of the
 CAP REQ parameter

Turns out it confuses inspircd, making it reply a NAK with empty
parameter. The rest is ACKed anyway. I've already whined at saberuk
and there's a pending pull request over there fixing this issue.

And, of course, this is cleaner.
---
 src/irc/core/irc-cap.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/irc/core/irc-cap.c b/src/irc/core/irc-cap.c
index cd3ae677..5464e493 100644
--- a/src/irc/core/irc-cap.c
+++ b/src/irc/core/irc-cap.c
@@ -112,7 +112,8 @@ static void event_cap (IRC_SERVER_REC *server, char *args, char *nick, char *add
 			/* Check whether the cap is supported by the server */
 			for (tmp = server->cap_queue; tmp != NULL; tmp = tmp->next) {
 				if (gslist_find_string(server->cap_supported, tmp->data)) {
-					g_string_append_c(cmd, ' ');
+					if (avail_caps > 0)
+						g_string_append_c(cmd, ' ');
 					g_string_append(cmd, tmp->data);
 
 					avail_caps++;

From 750df38e8ccd59d7cb3a11e09a682755060f7283 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Sun, 6 Dec 2015 22:31:49 +0100
Subject: [PATCH 0220/1650] Rewrite some faulty logic handling the saved
 channels.

Issue #340 brought to our attention the fact that under certain
circumstances irssi would go on a wild rampage and carelessly overwrite
some saved channel records in the configuration file.
This happened because the code didn't take into account the case where
the channel index in setupchannels wouldn't match the one in the
configuration; this actually happens when the user removes a chatnet
without removing the associated channels.
---
 src/core/channels-setup.c | 45 ++++++++++++++++++++++++++++++++-------
 1 file changed, 37 insertions(+), 8 deletions(-)

diff --git a/src/core/channels-setup.c b/src/core/channels-setup.c
index 2902ef8e..33f58022 100644
--- a/src/core/channels-setup.c
+++ b/src/core/channels-setup.c
@@ -30,16 +30,34 @@
 
 GSList *setupchannels;
 
+static int compare_channel_name (CONFIG_NODE *node, CHANNEL_SETUP_REC *channel)
+{
+	char *name, *chatnet;
+
+	name = config_node_get_str(node, "name", NULL);
+	chatnet = config_node_get_str(node, "chatnet", NULL);
+
+	if (name == NULL || chatnet == NULL)
+		return 1;
+
+	return !!strcmp(name, channel->name) | !!strcmp(chatnet, channel->chatnet);
+}
+
 static void channel_setup_save(CHANNEL_SETUP_REC *channel)
 {
 	CONFIG_NODE *parentnode, *node;
-	int index;
-
-	index = g_slist_index(setupchannels, channel);
+	GSList *config_node;
 
 	parentnode = iconfig_node_traverse("(channels", TRUE);
-	node = config_node_nth(parentnode, index);
-	if (node == NULL)
+
+	/* Try to find this channel in the configuration */
+	config_node = g_slist_find_custom(parentnode->value, channel,
+					  (GCompareFunc)compare_channel_name);
+	if (config_node != NULL)
+		/* Let's update this channel record */
+		node = config_node->data;
+	else
+		/* Create a brand-new channel record */
 		node = iconfig_node_section(parentnode, NULL, NODE_TYPE_BLOCK);
 
         iconfig_node_clear(node);
@@ -65,10 +83,21 @@ void channel_setup_create(CHANNEL_SETUP_REC *channel)
 
 static void channel_config_remove(CHANNEL_SETUP_REC *channel)
 {
-	CONFIG_NODE *node;
+	CONFIG_NODE *parentnode;
+	GSList *config_node;
 
-	node = iconfig_node_traverse("channels", FALSE);
-	if (node != NULL) iconfig_node_list_remove(node, g_slist_index(setupchannels, channel));
+	parentnode = iconfig_node_traverse("channels", FALSE);
+
+	if (parentnode == NULL)
+		return;
+
+	/* Try to find this channel in the configuration */
+	config_node = g_slist_find_custom(parentnode->value, channel,
+					  (GCompareFunc)compare_channel_name);
+
+	if (config_node != NULL)
+		/* Delete the channel from the configuration */
+		iconfig_node_remove(parentnode, config_node->data);
 }
 
 static void channel_setup_destroy(CHANNEL_SETUP_REC *channel)

From ca96444784535222e41606bd179f511fca097057 Mon Sep 17 00:00:00 2001
From: Wieland Hoffmann 
Date: Wed, 9 Dec 2015 11:21:51 +0100
Subject: [PATCH 0221/1650] DCC close always requires a type

---
 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 c348b1ae..649cb12b 100644
--- a/docs/help/in/dcc.in
+++ b/docs/help/in/dcc.in
@@ -38,8 +38,8 @@
     /DCC CHAT mike
     /DCC GET bob 'summer vacation.mkv'
     /DCC SEND sarah documents/resume.pdf
-    /DCC CLOSE mike
-    /DCC CLOSE bob 'summer vacation.mkv'
+    /DCC CLOSE get mike
+    /DCC CLOSE send bob 'summer vacation.mkv'
 
 %9See also:%9 CD
 

From 3532fc46719ebbcfe83b5814f93ac9cb58eea220 Mon Sep 17 00:00:00 2001
From: Ailin Nemui 
Date: Fri, 22 Aug 2014 13:48:17 +0200
Subject: [PATCH 0222/1650] Add bindings for exec-type window items to Perl

These bindings were missing and resulted in non-hash non-undef active
entries when an interactive process is executing.
---
 src/perl/perl-common.c |  6 ++++--
 src/perl/ui/UI.xs      | 17 +++++++++++++++++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/perl/perl-common.c b/src/perl/perl-common.c
index dcda3bb5..d7a428e5 100644
--- a/src/perl/perl-common.c
+++ b/src/perl/perl-common.c
@@ -351,10 +351,12 @@ void perl_window_item_fill_hash(HV *hv, WI_ITEM_REC *item)
         g_return_if_fail(item != NULL);
 
 	type = (char *) module_find_id_str("WINDOW ITEM TYPE", item->type);
-	chat_type = (char *) chat_protocol_find_id(item->chat_type)->name;
 
 	(void) hv_store(hv, "type", 4, new_pv(type), 0);
-	(void) hv_store(hv, "chat_type", 9, new_pv(chat_type), 0);
+	if (item->chat_type) {
+		chat_type = (char *) chat_protocol_find_id(item->chat_type)->name;
+		(void) hv_store(hv, "chat_type", 9, new_pv(chat_type), 0);
+	}
 
 	if (item->server != NULL) {
 		(void) hv_store(hv, "server", 6, iobject_bless(item->server), 0);
diff --git a/src/perl/ui/UI.xs b/src/perl/ui/UI.xs
index 9db57e98..5ac3da4e 100644
--- a/src/perl/ui/UI.xs
+++ b/src/perl/ui/UI.xs
@@ -64,6 +64,19 @@ static void perl_text_dest_fill_hash(HV *hv, TEXT_DEST_REC *dest)
 	(void) hv_store(hv, "hilight_color", 13, new_pv(dest->hilight_color), 0);
 }
 
+static void perl_exec_fill_hash(HV *hv, EXEC_WI_REC *item)
+{
+	g_return_if_fail(hv != NULL);
+	g_return_if_fail(item != NULL);
+
+	perl_window_item_fill_hash(hv, (WI_ITEM_REC *) item);
+	/* we don't bless to Process here to avoid infinite recursion
+	   in the simplistic script binding */
+	if (item->process != NULL) {
+		(void) hv_store(hv, "process_id", 10, newSViv(item->process->id), 0);
+	}
+}
+
 static PLAIN_OBJECT_INIT_REC fe_plains[] = {
 	{ "Irssi::UI::Process", (PERL_OBJECT_FUNC) perl_process_fill_hash },
 	{ "Irssi::UI::Window", (PERL_OBJECT_FUNC) perl_window_fill_hash },
@@ -94,6 +107,10 @@ CODE:
 	initialized = TRUE;
 
         irssi_add_plains(fe_plains);
+        /* window items: fe-exec */
+        irssi_add_object(module_get_uniq_id_str("WINDOW ITEM TYPE", "EXEC"),
+			 0, "Irssi::UI::Exec",
+                         (PERL_OBJECT_FUNC) perl_exec_fill_hash);
         perl_themes_init();
 
 void

From 20fe5d0c7feea176129b6a31f2983b1b17689866 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Wed, 9 Dec 2015 14:23:15 +0100
Subject: [PATCH 0223/1650] add missing file to Makefile

---
 src/fe-common/irc/Makefile.am | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/fe-common/irc/Makefile.am b/src/fe-common/irc/Makefile.am
index a5dd4c77..bf88f5cd 100644
--- a/src/fe-common/irc/Makefile.am
+++ b/src/fe-common/irc/Makefile.am
@@ -37,6 +37,7 @@ libfe_common_irc_a_SOURCES = \
 pkginc_fe_common_ircdir=$(pkgincludedir)/src/fe-common/irc
 pkginc_fe_common_irc_HEADERS = \
 	fe-irc-server.h \
+	fe-irc-channels.h \
 	module.h \
 	module-formats.h
 

From 0fcfd37b83afb3ca9abe4cce6630080b850df2be Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Wed, 9 Dec 2015 15:00:25 +0100
Subject: [PATCH 0224/1650] Fix Out-of-tree build

Symlink irssi-version.h into build dir, restoring 550df275580b253e8c3ebb5dbfceef87311a63c9
---
 configure.ac | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configure.ac b/configure.ac
index 325b5e5d..c0efd5e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -659,6 +659,7 @@ AC_OUTPUT
 dnl ** for building from objdir
 old_dir=`pwd` && cd $srcdir && whole_dir=`pwd` && cd $old_dir
 if test "x$old_dir" != "x$whole_dir"; then
+	$LN_S $srcdir/irssi-version.h irssi-version.h
 	if test "x$want_perl" != "xno"; then
 		subdirfiles=""
 		for i in $whole_dir/src/perl/common $whole_dir/src/perl/irc $whole_dir/src/perl/ui $whole_dir/src/perl/textui; do

From 60c501625bbc450b8bd443a7cbccf897810634fc Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Wed, 9 Dec 2015 15:43:31 +0100
Subject: [PATCH 0225/1650] Better function naming

---
 src/core/channels-setup.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/core/channels-setup.c b/src/core/channels-setup.c
index 33f58022..b3039fb2 100644
--- a/src/core/channels-setup.c
+++ b/src/core/channels-setup.c
@@ -30,7 +30,7 @@
 
 GSList *setupchannels;
 
-static int compare_channel_name (CONFIG_NODE *node, CHANNEL_SETUP_REC *channel)
+static int compare_channel_setup (CONFIG_NODE *node, CHANNEL_SETUP_REC *channel)
 {
 	char *name, *chatnet;
 
@@ -52,7 +52,7 @@ static void channel_setup_save(CHANNEL_SETUP_REC *channel)
 
 	/* Try to find this channel in the configuration */
 	config_node = g_slist_find_custom(parentnode->value, channel,
-					  (GCompareFunc)compare_channel_name);
+					  (GCompareFunc)compare_channel_setup);
 	if (config_node != NULL)
 		/* Let's update this channel record */
 		node = config_node->data;
@@ -93,7 +93,7 @@ static void channel_config_remove(CHANNEL_SETUP_REC *channel)
 
 	/* Try to find this channel in the configuration */
 	config_node = g_slist_find_custom(parentnode->value, channel,
-					  (GCompareFunc)compare_channel_name);
+					  (GCompareFunc)compare_channel_setup);
 
 	if (config_node != NULL)
 		/* Delete the channel from the configuration */

From 971417caa342881780b347f6aca728d962d710ee Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Wed, 9 Dec 2015 16:02:37 +0100
Subject: [PATCH 0226/1650] Rewrite some faulty logic handling the saved
 servers.

---
 src/core/channels-setup.c | 23 ++++++++-------
 src/core/servers-setup.c  | 59 +++++++++++++++++++++++++++++----------
 2 files changed, 58 insertions(+), 24 deletions(-)

diff --git a/src/core/channels-setup.c b/src/core/channels-setup.c
index b3039fb2..dd722fea 100644
--- a/src/core/channels-setup.c
+++ b/src/core/channels-setup.c
@@ -40,25 +40,28 @@ static int compare_channel_setup (CONFIG_NODE *node, CHANNEL_SETUP_REC *channel)
 	if (name == NULL || chatnet == NULL)
 		return 1;
 
-	return !!strcmp(name, channel->name) | !!strcmp(chatnet, channel->chatnet);
+	if (strcmp(name, channel->name) || strcmp(chatnet, channel->chatnet))
+		return 1;
+
+	return 0;
 }
 
 static void channel_setup_save(CHANNEL_SETUP_REC *channel)
 {
-	CONFIG_NODE *parentnode, *node;
+	CONFIG_NODE *parent_node, *node;
 	GSList *config_node;
 
-	parentnode = iconfig_node_traverse("(channels", TRUE);
+	parent_node = iconfig_node_traverse("(channels", TRUE);
 
 	/* Try to find this channel in the configuration */
-	config_node = g_slist_find_custom(parentnode->value, channel,
+	config_node = g_slist_find_custom(parent_node->value, channel,
 					  (GCompareFunc)compare_channel_setup);
 	if (config_node != NULL)
 		/* Let's update this channel record */
 		node = config_node->data;
 	else
 		/* Create a brand-new channel record */
-		node = iconfig_node_section(parentnode, NULL, NODE_TYPE_BLOCK);
+		node = iconfig_node_section(parent_node, NULL, NODE_TYPE_BLOCK);
 
         iconfig_node_clear(node);
 	iconfig_node_set_str(node, "name", channel->name);
@@ -83,21 +86,21 @@ void channel_setup_create(CHANNEL_SETUP_REC *channel)
 
 static void channel_config_remove(CHANNEL_SETUP_REC *channel)
 {
-	CONFIG_NODE *parentnode;
+	CONFIG_NODE *parent_node;
 	GSList *config_node;
 
-	parentnode = iconfig_node_traverse("channels", FALSE);
+	parent_node = iconfig_node_traverse("channels", FALSE);
 
-	if (parentnode == NULL)
+	if (parent_node == NULL)
 		return;
 
 	/* Try to find this channel in the configuration */
-	config_node = g_slist_find_custom(parentnode->value, channel,
+	config_node = g_slist_find_custom(parent_node->value, channel,
 					  (GCompareFunc)compare_channel_setup);
 
 	if (config_node != NULL)
 		/* Delete the channel from the configuration */
-		iconfig_node_remove(parentnode, config_node->data);
+		iconfig_node_remove(parent_node, config_node->data);
 }
 
 static void channel_setup_destroy(CHANNEL_SETUP_REC *channel)
diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index 771e3999..26632d63 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -423,17 +423,41 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
 	return rec;
 }
 
+static int compare_server_setup (CONFIG_NODE *node, SERVER_SETUP_REC *server)
+{
+	char *address, *chatnet;
+	int port;
+
+	address = config_node_get_str(node, "address", NULL);
+	chatnet = config_node_get_str(node, "chatnet", NULL);
+	port = config_node_get_int(node, "port", 0);
+
+	if (address == NULL || chatnet == NULL)
+		return 1;
+
+	if (strcmp(address, server->address) || strcmp(chatnet, server->chatnet)
+	    || port != server->port)
+		return 1;
+
+	return 0;
+}
+
 static void server_setup_save(SERVER_SETUP_REC *rec)
 {
-	CONFIG_NODE *parentnode, *node;
-	int index;
+	CONFIG_NODE *parent_node, *node;
+	GSList *config_node;
 
-	index = g_slist_index(setupservers, rec);
+	parent_node = iconfig_node_traverse("(servers", TRUE);
 
-	parentnode = iconfig_node_traverse("(servers", TRUE);
-	node = config_node_nth(parentnode, index);
-	if (node == NULL)
-		node = iconfig_node_section(parentnode, NULL, NODE_TYPE_BLOCK);
+	/* Try to find this channel in the configuration */
+	config_node = g_slist_find_custom(parent_node->value, rec,
+					  (GCompareFunc)compare_server_setup);
+	if (config_node != NULL)
+		/* Let's update this server record */
+		node = config_node->data;
+	else
+		/* Create a brand-new server record */
+		node = iconfig_node_section(parent_node, NULL, NODE_TYPE_BLOCK);
 
         iconfig_node_clear(node);
 	iconfig_node_set_str(node, "address", rec->address);
@@ -465,14 +489,21 @@ static void server_setup_save(SERVER_SETUP_REC *rec)
 
 static void server_setup_remove_config(SERVER_SETUP_REC *rec)
 {
-	CONFIG_NODE *node;
-	int index;
+	CONFIG_NODE *parent_node;
+	GSList *config_node;
 
-	node = iconfig_node_traverse("servers", FALSE);
-	if (node != NULL) {
-		index = g_slist_index(setupservers, rec);
-		iconfig_node_list_remove(node, index);
-	}
+	parent_node = iconfig_node_traverse("servers", FALSE);
+
+	if (parent_node == NULL)
+		return;
+
+	/* Try to find this server in the configuration */
+	config_node = g_slist_find_custom(parent_node->value, rec,
+					  (GCompareFunc)compare_server_setup);
+
+	if (config_node != NULL)
+		/* Delete the server from the configuration */
+		iconfig_node_remove(parent_node, config_node->data);
 }
 
 static void server_setup_destroy(SERVER_SETUP_REC *rec)

From 1749a7a5abf9801bb663b74d4b3e7c3bcbfeb271 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Wed, 9 Dec 2015 16:16:03 +0100
Subject: [PATCH 0227/1650] Minor adjustments.

Use g_strcmp0 instead of strcmp.
Explicit checks added for the g_strcmp0 clauses.
---
 src/core/channels-setup.c | 6 ++----
 src/core/servers-setup.c  | 8 +++-----
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/src/core/channels-setup.c b/src/core/channels-setup.c
index dd722fea..4966d77d 100644
--- a/src/core/channels-setup.c
+++ b/src/core/channels-setup.c
@@ -37,10 +37,8 @@ static int compare_channel_setup (CONFIG_NODE *node, CHANNEL_SETUP_REC *channel)
 	name = config_node_get_str(node, "name", NULL);
 	chatnet = config_node_get_str(node, "chatnet", NULL);
 
-	if (name == NULL || chatnet == NULL)
-		return 1;
-
-	if (strcmp(name, channel->name) || strcmp(chatnet, channel->chatnet))
+	if (g_strcmp0(name, channel->name) != 0 || 
+	    g_strcmp0(chatnet, channel->chatnet) != 0)
 		return 1;
 
 	return 0;
diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index 26632d63..4a048282 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -432,11 +432,9 @@ static int compare_server_setup (CONFIG_NODE *node, SERVER_SETUP_REC *server)
 	chatnet = config_node_get_str(node, "chatnet", NULL);
 	port = config_node_get_int(node, "port", 0);
 
-	if (address == NULL || chatnet == NULL)
-		return 1;
-
-	if (strcmp(address, server->address) || strcmp(chatnet, server->chatnet)
-	    || port != server->port)
+	if (g_strcmp0(address, server->address) != 0 ||
+	    g_strcmp0(chatnet, server->chatnet) != 0 ||
+	    port != server->port)
 		return 1;
 
 	return 0;

From 96766b7f0530ca2e5b4d0fde68337f956e46eb0e Mon Sep 17 00:00:00 2001
From: dequis 
Date: Wed, 9 Dec 2015 15:20:59 -0300
Subject: [PATCH 0228/1650] Remove all WIN32 ifdefs (unifdef -UWIN32)

Just use cygwin.

This looks like it wasn't enough to do anything useful, and I don't
think anyone cares about supporting win32 the hard way.
---
 src/common.h                        |  3 ---
 src/core/core.c                     |  6 ------
 src/core/misc.c                     |  4 ----
 src/core/net-disconnect.c           |  2 --
 src/core/net-nonblock.c             | 10 ----------
 src/core/net-sendbuffer.c           |  4 ----
 src/core/network.c                  | 16 ----------------
 src/core/network.h                  |  2 --
 src/fe-common/core/fe-common-core.c |  4 ----
 src/fe-text/irssi.c                 | 17 -----------------
 10 files changed, 68 deletions(-)

diff --git a/src/common.h b/src/common.h
index 86a079fe..0cf951b3 100644
--- a/src/common.h
+++ b/src/common.h
@@ -34,9 +34,6 @@
 #  include 
 #endif
 #include 
-#ifdef WIN32
-#  include 
-#endif
 
 #include 
 #ifdef HAVE_GMODULE
diff --git a/src/core/core.c b/src/core/core.c
index bbeec6f4..bf7cdd6b 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -83,7 +83,6 @@ static void sig_reload_config(int signo)
 
 static void read_settings(void)
 {
-#ifndef WIN32
 	static int signals[] = {
 		SIGINT, SIGQUIT, SIGTERM,
 		SIGALRM, SIGUSR1, SIGUSR2
@@ -124,7 +123,6 @@ static void read_settings(void)
                         settings_set_bool("override_coredump_limit", FALSE);
 	}
 #endif
-#endif
 }
 
 static void sig_gui_dialog(const char *type, const char *text)
@@ -225,9 +223,7 @@ void core_init(void)
 	client_start_time = time(NULL);
 
 	modules_init();
-#ifndef WIN32
 	pidwait_init();
-#endif
 
 	net_disconnect_init();
 	signals_init();
@@ -303,9 +299,7 @@ void core_deinit(void)
 	signals_deinit();
 	net_disconnect_deinit();
 
-#ifndef WIN32
 	pidwait_deinit();
-#endif
 	modules_deinit();
 
 	g_free(irssi_dir);
diff --git a/src/core/misc.c b/src/core/misc.c
index 490b5a8f..aaa470f5 100644
--- a/src/core/misc.c
+++ b/src/core/misc.c
@@ -430,11 +430,7 @@ int mkpath(const char *path, int mode)
 
 		dir = g_strndup(path, (int) (p-path));
 		if (stat(dir, &statbuf) != 0) {
-#ifndef WIN32
 			if (mkdir(dir, mode) == -1)
-#else
-			if (_mkdir(dir) == -1)
-#endif
 			{
 				g_free(dir);
 				return -1;
diff --git a/src/core/net-disconnect.c b/src/core/net-disconnect.c
index 321f79ac..6476e776 100644
--- a/src/core/net-disconnect.c
+++ b/src/core/net-disconnect.c
@@ -116,7 +116,6 @@ void net_disconnect_init(void)
 
 void net_disconnect_deinit(void)
 {
-#ifndef WIN32
 	NET_DISCONNECT_REC *rec;
 	time_t now, max;
 	int first, fd;
@@ -155,5 +154,4 @@ void net_disconnect_deinit(void)
 			first = 0;
 		}
 	}
-#endif
 }
diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c
index e637e673..d6e767b6 100644
--- a/src/core/net-nonblock.c
+++ b/src/core/net-nonblock.c
@@ -77,14 +77,11 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe,
 {
 	RESOLVED_IP_REC rec;
 	const char *errorstr;
-#ifndef WIN32
 	int pid;
-#endif
 	int len;
 
 	g_return_val_if_fail(addr != NULL, FALSE);
 
-#ifndef WIN32
 	pid = fork();
 	if (pid > 0) {
 		/* parent */
@@ -97,7 +94,6 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe,
 		g_warning("net_connect_thread(): fork() failed! "
 			  "Using blocking resolving");
 	}
-#endif
 
 	/* child */
 	srand(time(NULL));
@@ -138,10 +134,8 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe,
 		}
 	}
 
-#ifndef WIN32
 	if (pid == 0)
 		_exit(99);
-#endif
 
 	/* we used blocking lookup */
 	return 0;
@@ -157,9 +151,7 @@ int net_gethostbyname_return(GIOChannel *pipe, RESOLVED_IP_REC *rec)
 	rec->host4 = NULL;
 	rec->host6 = NULL;
 
-#ifndef WIN32
 	fcntl(g_io_channel_unix_get_fd(pipe), F_SETFL, O_NONBLOCK);
-#endif
 
 	/* get ip+error */
 	if (g_io_channel_read_block(pipe, rec, sizeof(*rec)) == -1) {
@@ -201,9 +193,7 @@ void net_disconnect_nonblock(int pid)
 {
 	g_return_if_fail(pid > 0);
 
-#ifndef WIN32
 	kill(pid, SIGKILL);
-#endif
 }
 
 static void simple_init(SIMPLE_THREAD_REC *rec, GIOChannel *handle)
diff --git a/src/core/net-sendbuffer.c b/src/core/net-sendbuffer.c
index 39257486..97fb551f 100644
--- a/src/core/net-sendbuffer.c
+++ b/src/core/net-sendbuffer.c
@@ -160,13 +160,9 @@ void net_sendbuffer_flush(NET_SENDBUF_REC *rec)
 
         /* set the socket blocking while doing this */
 	handle = g_io_channel_unix_get_fd(rec->handle);
-#ifndef WIN32
 	fcntl(handle, F_SETFL, 0);
-#endif
 	while (!buffer_send(rec)) ;
-#ifndef WIN32
 	fcntl(handle, F_SETFL, O_NONBLOCK);
-#endif
 }
 
 /* Returns the socket handle */
diff --git a/src/core/network.c b/src/core/network.c
index bfaa47fb..0751aa95 100644
--- a/src/core/network.c
+++ b/src/core/network.c
@@ -45,11 +45,7 @@ union sockaddr_union {
 GIOChannel *g_io_channel_new(int handle)
 {
 	GIOChannel *chan;
-#ifdef WIN32
-	chan = g_io_channel_win32_new_socket(handle);
-#else
 	chan = g_io_channel_unix_new(handle);
-#endif
 	g_io_channel_set_encoding(chan, NULL, NULL);
 	g_io_channel_set_buffered(chan, FALSE);
 	return chan;
@@ -188,9 +184,7 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
 		return NULL;
 
 	/* set socket options */
-#ifndef WIN32
 	fcntl(handle, F_SETFL, O_NONBLOCK);
-#endif
 	setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 	setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt));
 
@@ -211,11 +205,7 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
 	sin_set_port(&so, port);
 	ret = connect(handle, &so.sa, SIZEOF_SOCKADDR(so));
 
-#ifndef WIN32
 	if (ret < 0 && errno != EINPROGRESS)
-#else
-	if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
-#endif
 	{
 		int old_errno = errno;
 		close(handle);
@@ -238,9 +228,7 @@ GIOChannel *net_connect_unix(const char *path)
 		return NULL;
 
 	/* set socket options */
-#ifndef WIN32
 	fcntl(handle, F_SETFL, O_NONBLOCK);
-#endif
 
 	/* connect */
 	memset(&sa, 0, sizeof(sa));
@@ -297,9 +285,7 @@ GIOChannel *net_listen(IPADDR *my_ip, int *port)
 		return NULL;
 
 	/* set socket options */
-#ifndef WIN32
 	fcntl(handle, F_SETFL, O_NONBLOCK);
-#endif
 	setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 	setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt));
 
@@ -342,9 +328,7 @@ GIOChannel *net_accept(GIOChannel *handle, IPADDR *addr, int *port)
 	if (addr != NULL) sin_get_ip(&so, addr);
 	if (port != NULL) *port = sin_get_port(&so);
 
-#ifndef WIN32
 	fcntl(ret, F_SETFL, O_NONBLOCK);
-#endif
 	return g_io_channel_new(ret);
 }
 
diff --git a/src/core/network.h b/src/core/network.h
index fa7e9675..73ac8dee 100644
--- a/src/core/network.h
+++ b/src/core/network.h
@@ -6,12 +6,10 @@
 #endif
 
 #include 
-#ifndef WIN32
 #  include 
 #  include 
 #  include 
 #  include 
-#endif
 
 #ifndef AF_INET6
 #  ifdef PF_INET6
diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c
index a15850e2..ee7f9424 100644
--- a/src/fe-common/core/fe-common-core.c
+++ b/src/fe-common/core/fe-common-core.c
@@ -168,9 +168,7 @@ void fe_common_core_init(void)
 	keyboard_init();
 	printtext_init();
 	formats_init();
-#ifndef WIN32
         fe_exec_init();
-#endif
         fe_expandos_init();
 	fe_help_init();
 	fe_ignore_init();
@@ -211,9 +209,7 @@ void fe_common_core_deinit(void)
 	keyboard_deinit();
 	printtext_deinit();
 	formats_deinit();
-#ifndef WIN32
         fe_exec_deinit();
-#endif
         fe_expandos_deinit();
 	fe_help_deinit();
 	fe_ignore_deinit();
diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c
index b1fa5e22..cad271c9 100644
--- a/src/fe-text/irssi.c
+++ b/src/fe-text/irssi.c
@@ -271,20 +271,6 @@ static void check_files(void)
 	}
 }
 
-#ifdef WIN32
-static void winsock_init(void)
-{
-	WORD wVersionRequested;
-	WSADATA wsaData;
-
-	wVersionRequested = MAKEWORD(2, 2);
-
-	if (WSAStartup(wVersionRequested, &wsaData) != 0) {
-		printf("Error initializing winsock\n");
-		exit(1);
-	}
-}
-#endif
 
 int main(int argc, char **argv)
 {
@@ -315,9 +301,6 @@ int main(int argc, char **argv)
 
 	check_files();
 
-#ifdef WIN32
-        winsock_init();
-#endif
 #ifdef HAVE_SOCKS
 	SOCKSinit(argv[0]);
 #endif

From ff8ccaf08b60d88a67ddf810f8229f910f016cf7 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Tue, 24 Nov 2015 00:08:20 +0100
Subject: [PATCH 0229/1650] module check irssi version

Add explicit checks into every module to match the ABI version defined
in common.h
---
 src/common.h                        |  2 ++
 src/core/expandos.c                 |  9 +++++++++
 src/core/modules-load.c             | 26 +++++++++++++++++++++++++-
 src/core/modules.h                  |  1 +
 src/fe-common/core/fe-modules.c     |  4 ++++
 src/fe-common/core/module-formats.c |  1 +
 src/fe-common/core/module-formats.h |  1 +
 src/irc/proxy/proxy.c               |  5 +++++
 src/perl/perl-core.c                |  5 +++++
 src/perl/perl-fe.c                  |  5 +++++
 10 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/src/common.h b/src/common.h
index 0cf951b3..966e28d0 100644
--- a/src/common.h
+++ b/src/common.h
@@ -6,6 +6,8 @@
 #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 DEFAULT_SERVER_ADD_PORT 6667
 
 #ifdef HAVE_CONFIG_H
diff --git a/src/core/expandos.c b/src/core/expandos.c
index 1fc517af..67aea837 100644
--- a/src/core/expandos.c
+++ b/src/core/expandos.c
@@ -414,6 +414,13 @@ static char *expando_releasetime(SERVER_REC *server, void *item, int *free_ret)
 	return g_strdup_printf("%04d", IRSSI_VERSION_TIME);
 }
 
+/* client abi */
+static char *expando_abiversion(SERVER_REC *server, void *item, int *free_ret)
+{
+        *free_ret = TRUE;
+	return g_strdup_printf("%d", IRSSI_ABI_VERSION);
+}
+
 /* current working directory */
 static char *expando_workdir(SERVER_REC *server, void *item, int *free_ret)
 {
@@ -658,6 +665,8 @@ void expandos_init(void)
 		       "", EXPANDO_NEVER, NULL);
 	expando_create("versiontime", expando_releasetime,
 		       "", EXPANDO_NEVER, NULL);
+	expando_create("abiversion", expando_abiversion,
+		       "", EXPANDO_NEVER, NULL);
 	expando_create("W", expando_workdir, NULL);
 	expando_create("Y", expando_realname,
 		       "window changed", EXPANDO_ARG_NONE,
diff --git a/src/core/modules-load.c b/src/core/modules-load.c
index 6086d9ae..9baac1d7 100644
--- a/src/core/modules-load.c
+++ b/src/core/modules-load.c
@@ -160,11 +160,14 @@ static int module_load_name(const char *path, const char *rootmodule,
 {
 	void (*module_init) (void);
 	void (*module_deinit) (void);
+	void (*module_version) (int *);
 	GModule *gmodule;
         MODULE_REC *module;
 	MODULE_FILE_REC *rec;
+	gpointer value_version = NULL;
 	gpointer value1, value2 = NULL;
-	char *initfunc, *deinitfunc;
+	char *versionfunc, *initfunc, *deinitfunc;
+	int module_abi_version = 0;
         int found;
 
 	gmodule = module_open(path, &found);
@@ -176,6 +179,27 @@ static int module_load_name(const char *path, const char *rootmodule,
 		return found ? 0 : -1;
 	}
 
+	/* get the module's irssi abi version and bail out on mismatch */
+	versionfunc = module_get_func(rootmodule, submodule, "abicheck");
+	if (!g_module_symbol(gmodule, versionfunc, &value_version)) {
+		g_free(versionfunc);
+		module_error(MODULE_ERROR_VERSION_MISMATCH, "0",
+			     rootmodule, submodule);
+		g_module_close(gmodule);
+		return 0;
+	}
+	g_free(versionfunc);
+	module_version = value_version;
+	module_version(&module_abi_version);
+	if (module_abi_version != IRSSI_ABI_VERSION) {
+		char *module_abi_versionstr = g_strdup_printf("%d", module_abi_version);
+		module_error(MODULE_ERROR_VERSION_MISMATCH, module_abi_versionstr,
+			     rootmodule, submodule);
+		g_free(module_abi_versionstr);
+		g_module_close(gmodule);
+		return 0;
+	}
+
 	/* get the module's init() and deinit() functions */
 	initfunc = module_get_func(rootmodule, submodule, "init");
 	deinitfunc = module_get_func(rootmodule, submodule, "deinit");
diff --git a/src/core/modules.h b/src/core/modules.h
index 75a77c77..b2fa2fa4 100644
--- a/src/core/modules.h
+++ b/src/core/modules.h
@@ -27,6 +27,7 @@
 enum {
 	MODULE_ERROR_ALREADY_LOADED,
 	MODULE_ERROR_LOAD,
+	MODULE_ERROR_VERSION_MISMATCH,
 	MODULE_ERROR_INVALID
 };
 
diff --git a/src/fe-common/core/fe-modules.c b/src/fe-common/core/fe-modules.c
index df97ceb1..27b6b4c1 100644
--- a/src/fe-common/core/fe-modules.c
+++ b/src/fe-common/core/fe-modules.c
@@ -43,6 +43,10 @@ static void sig_module_error(void *number, const char *data,
 		printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
 			    TXT_MODULE_LOAD_ERROR, rootmodule, submodule, data);
 		break;
+	case MODULE_ERROR_VERSION_MISMATCH:
+		printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
+			    TXT_MODULE_VERSION_MISMATCH, rootmodule, submodule, data);
+		break;
 	case MODULE_ERROR_INVALID:
 		printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
 			    TXT_MODULE_INVALID, rootmodule, submodule);
diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c
index 4ae26950..e6d32b6d 100644
--- a/src/fe-common/core/module-formats.c
+++ b/src/fe-common/core/module-formats.c
@@ -196,6 +196,7 @@ FORMAT_REC fecommon_core_formats[] = {
 	{ "module_already_loaded", "Module {hilight $0/$1} already loaded", 2, { 0, 0 } },
 	{ "module_not_loaded", "Module {hilight $0/$1} is not loaded", 2, { 0, 0 } },
 	{ "module_load_error", "Error loading module {hilight $0/$1}: $2", 3, { 0, 0, 0 } },
+	{ "module_version_mismatch", "{hilight $0/$1} is ABI version $2 but Irssi is version $abiversion, cannot load", 3, { 0, 0, 0 } },
 	{ "module_invalid", "{hilight $0/$1} isn't Irssi module", 2, { 0, 0 } },
 	{ "module_loaded", "Loaded module {hilight $0/$1}", 2, { 0, 0 } },
 	{ "module_unloaded", "Unloaded module {hilight $0/$1}", 2, { 0, 0 } },
diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h
index 18bf91f5..3f06bb97 100644
--- a/src/fe-common/core/module-formats.h
+++ b/src/fe-common/core/module-formats.h
@@ -166,6 +166,7 @@ enum {
 	TXT_MODULE_ALREADY_LOADED,
 	TXT_MODULE_NOT_LOADED,
 	TXT_MODULE_LOAD_ERROR,
+	TXT_MODULE_VERSION_MISMATCH,
 	TXT_MODULE_INVALID,
 	TXT_MODULE_LOADED,
 	TXT_MODULE_UNLOADED,
diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c
index ce79e2b7..50a41b21 100644
--- a/src/irc/proxy/proxy.c
+++ b/src/irc/proxy/proxy.c
@@ -108,3 +108,8 @@ void irc_proxy_deinit(void)
 {
 	proxy_listen_deinit();
 }
+
+void irc_proxy_abicheck(int *version)
+{
+	*version = IRSSI_ABI_VERSION;
+}
diff --git a/src/perl/perl-core.c b/src/perl/perl-core.c
index 793f9375..2f28c718 100644
--- a/src/perl/perl-core.c
+++ b/src/perl/perl-core.c
@@ -466,3 +466,8 @@ void perl_core_deinit(void)
 	signal_remove("script error", (SIGNAL_FUNC) sig_script_error);
 	PERL_SYS_TERM();
 }
+
+void perl_core_abicheck(int *version)
+{
+	*version = IRSSI_ABI_VERSION;
+}
diff --git a/src/perl/perl-fe.c b/src/perl/perl-fe.c
index 2abc75c0..04305b63 100644
--- a/src/perl/perl-fe.c
+++ b/src/perl/perl-fe.c
@@ -278,3 +278,8 @@ void fe_perl_deinit(void)
 
         perl_core_print_script_error(TRUE);
 }
+
+void fe_perl_abicheck(int *version)
+{
+	*version = IRSSI_ABI_VERSION;
+}

From 9dd2b7c616e48a7525e72d6798a0adae34720616 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Thu, 10 Dec 2015 14:02:59 +0100
Subject: [PATCH 0230/1650] deinit perl on staticperl builds

---
 src/perl/perl-core.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/perl/perl-core.c b/src/perl/perl-core.c
index 793f9375..2c0ca49d 100644
--- a/src/perl/perl-core.c
+++ b/src/perl/perl-core.c
@@ -82,16 +82,18 @@ static void perl_script_destroy(PERL_SCRIPT_REC *script)
 extern void boot_DynaLoader(pTHX_ CV* cv);
 
 #if PERL_STATIC_LIBS == 1
-extern void boot_Irssi(CV *cv);
+extern void boot_Irssi(pTHX_ CV *cv);
 
 XS(boot_Irssi_Core)
 {
 	dXSARGS;
+	PERL_UNUSED_VAR(items);
 
 	irssi_callXS(boot_Irssi, cv, mark);
         irssi_boot(Irc);
         irssi_boot(UI);
         irssi_boot(TextUI);
+	/* Make sure to keep this in line with perl_scripts_deinit below. */
 	XSRETURN_YES;
 }
 #endif
@@ -155,6 +157,17 @@ void perl_scripts_deinit(void)
 	/* Unload all perl libraries loaded with dynaloader */
 	perl_eval_pv("foreach my $lib (@DynaLoader::dl_modules) { if ($lib =~ /^Irssi\\b/) { $lib .= '::deinit();'; eval $lib; } }", TRUE);
 
+#if PERL_STATIC_LIBS == 1
+	/* If perl is statically built we should manually deinit the modules
+	   which are booted in boot_Irssi_Core above */
+	perl_eval_pv("foreach my $lib (qw("
+		"Irssi" " "
+		"Irssi::Irc" " "
+		"Irssi::UI" " "
+		"Irssi::TextUI"
+		")) { eval $lib . '::deinit();'; }", TRUE);
+#endif
+
 	/* We could unload all libraries .. but this crashes with some
 	   libraries, probably because we don't call some deinit function..
 	   Anyway, this would free some memory with /SCRIPT RESET, but it

From 0b1a912f822b21e5c4dfc18436ab5b90f079e19b Mon Sep 17 00:00:00 2001
From: dequis 
Date: Fri, 11 Dec 2015 21:31:04 -0300
Subject: [PATCH 0231/1650] Makefile.am: Add default-config.h and
 default-theme.h to CLEANFILES

Fixes issues when building from other directories when the source tree
was already configured before, as found in the comments of PR #375
---
 Makefile.am | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Makefile.am b/Makefile.am
index 6ca69fc7..75d502f1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,6 +2,7 @@ ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
 
 # create default-config.h
 BUILT_SOURCES = default-config.h default-theme.h irssi-version.h
+CLEANFILES = default-config.h default-theme.h
 
 @MAINTAINER_MODE_TRUE@.PHONY: irssi-version.h
 

From 38d372eccb3745a7734b8f8963ae572d1343c5b1 Mon Sep 17 00:00:00 2001
From: dequis 
Date: Sat, 12 Dec 2015 01:17:48 -0300
Subject: [PATCH 0232/1650] Disable timeout-based paste detection if
 paste_use_bracketed_mode is on

---
 src/fe-text/gui-readline.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index 96b8b386..a9755318 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -737,7 +737,7 @@ static void sig_input(void)
 		if (paste_bracketed_mode) {
 			paste_bracketed_middle();
 
-		} else if (paste_detect_time > 0 && paste_buffer->len >= 3) {
+		} else if (!paste_use_bracketed_mode && paste_detect_time > 0 && paste_buffer->len >= 3) {
 			if (paste_timeout_id != -1)
 				g_source_remove(paste_timeout_id);
 			paste_timeout_id = g_timeout_add(paste_detect_time, paste_timeout, NULL);

From e6fa311590da78d05e9eea42d3664cec01c9b1ae Mon Sep 17 00:00:00 2001
From: dequis 
Date: Sat, 12 Dec 2015 01:44:05 -0300
Subject: [PATCH 0233/1650] Bracketed paste: Adjust paste line count if there's
 text after newlines

With bracketed paste, "a\nb" will result in two lines being pasted,
because it's a single thing, with an end marker which the timeout based
pastes don't have.

Due to the way term_gets() counts lines, that input will have
paste_line_count == 1. This can be misleading.

This code adjusts it by looking at the last character, and increasing
the count if it finds anything that isn't a newline.
---
 src/fe-text/gui-readline.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index a9755318..851cbbe6 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -660,6 +660,8 @@ static gboolean paste_timeout(gpointer data)
 
 static void paste_bracketed_end(int i, gboolean rest)
 {
+	unichar last_char;
+
 	/* if there's stuff after the end bracket, save it for later */
 	if (rest) {
 		unichar *start = ((unichar *) paste_buffer->data) + i + G_N_ELEMENTS(bp_end);
@@ -672,6 +674,14 @@ static void paste_bracketed_end(int i, gboolean rest)
 	/* remove the rest, including the trailing sequence chars */
 	g_array_set_size(paste_buffer, i);
 
+	last_char = g_array_index(paste_buffer, unichar, i - 1);
+
+	if (paste_line_count > 0 && last_char != '\n' && last_char != '\r') {
+		/* there are newlines, but there's also stuff after the newline
+		 * adjust line count to reflect this */
+		paste_line_count++;
+	}
+
 	/* decide what to do with the buffer */
 	paste_timeout(NULL);
 

From 6e01a2313439bb02a66a52db645f63f078c2c4b0 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Sun, 13 Dec 2015 01:08:53 +0100
Subject: [PATCH 0234/1650] ensure staticlib perl works on 5.22 (for now)

---
 src/perl/perl-common.c | 3 ---
 src/perl/perl-core.c   | 2 +-
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/perl/perl-common.c b/src/perl/perl-common.c
index d7a428e5..b641867f 100644
--- a/src/perl/perl-common.c
+++ b/src/perl/perl-common.c
@@ -246,10 +246,7 @@ char *perl_get_use_list(void)
 
 void irssi_callXS(void (*subaddr)(pTHX_ CV* cv), CV *cv, SV **mark)
 {
-	dSP;
-
 	PUSHMARK(mark);
-	PUTBACK;
 
 	(*subaddr)(aTHX_ cv);
 }
diff --git a/src/perl/perl-core.c b/src/perl/perl-core.c
index 2c0ca49d..1a864ef7 100644
--- a/src/perl/perl-core.c
+++ b/src/perl/perl-core.c
@@ -125,7 +125,7 @@ void perl_scripts_init(void)
 
 	perl_parse(my_perl, xs_init, G_N_ELEMENTS(perl_args), perl_args, NULL);
 #if PERL_STATIC_LIBS == 1
-	perl_eval_pv("Irssi::Core::boot_Irssi_Core();", TRUE);
+	perl_eval_pv("Irssi::Core::->boot_Irssi_Core(0.9);", TRUE);
 #endif
 
         perl_common_start();

From ce77842a985edc82aa1ca30c83c4edfe904872aa Mon Sep 17 00:00:00 2001
From: dequis 
Date: Sun, 13 Dec 2015 13:56:09 -0300
Subject: [PATCH 0235/1650] Bracketed paste: fix nitpick from ahf's review

Thanks ahf
---
 src/fe-text/gui-readline.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index 851cbbe6..f531d282 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -339,7 +339,7 @@ static void paste_flush(int send)
 	g_array_set_size(paste_buffer, 0);
 
 	/* re-add anything that may have been after the bracketed paste end */
-	if (paste_buffer_rest->len) {
+	if (paste_buffer_rest->len > 0) {
 		g_array_append_vals(paste_buffer, paste_buffer_rest->data, paste_buffer_rest->len);
 		g_array_set_size(paste_buffer_rest, 0);
 	}

From 620d0a9299d31e3f9b59233904151cdce4519526 Mon Sep 17 00:00:00 2001
From: mh 
Date: Mon, 14 Dec 2015 19:12:47 +0100
Subject: [PATCH 0236/1650] script should be plural

---
 docs/perl.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/perl.txt b/docs/perl.txt
index 560fcaec..9688341f 100644
--- a/docs/perl.txt
+++ b/docs/perl.txt
@@ -10,7 +10,7 @@ INSTALL file for information about perl problems.
  ---------------
 
 Scripts are run with /SCRIPT LOAD command, or the default /RUN alias.
-"/SCRIPT" shows list of running script, and /SCRIPT UNLOAD can unload
+"/SCRIPT" shows list of running scripts, and /SCRIPT UNLOAD can unload
 scripts.
 
 Scripts should be placed to ~/.irssi/scripts/ or

From 5fbad764df7b96618553a45facde73edb5e7bb9c Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Tue, 15 Dec 2015 00:08:44 +0100
Subject: [PATCH 0237/1650] clean up after #303

---
 src/fe-common/core/formats.h      | 1 -
 src/fe-common/core/hilight-text.h | 2 --
 2 files changed, 3 deletions(-)

diff --git a/src/fe-common/core/formats.h b/src/fe-common/core/formats.h
index 484105f9..a4b26852 100644
--- a/src/fe-common/core/formats.h
+++ b/src/fe-common/core/formats.h
@@ -45,7 +45,6 @@ struct _FORMAT_REC {
 #define PRINT_FLAG_SET_SERVERTAG	0x0010
 #define PRINT_FLAG_UNSET_SERVERTAG	0x0020
 
-// FIXME: sould use better
 typedef struct _HILIGHT_REC HILIGHT_REC;
 
 typedef struct _TEXT_DEST_REC {
diff --git a/src/fe-common/core/hilight-text.h b/src/fe-common/core/hilight-text.h
index fa083882..3c897def 100644
--- a/src/fe-common/core/hilight-text.h
+++ b/src/fe-common/core/hilight-text.h
@@ -7,8 +7,6 @@
 
 #include "formats.h"
 
-//typedef struct _HILIGHT_REC HILIGHT_REC;
-
 struct _HILIGHT_REC {
 	char *text;
 

From e4e040929b247b2432190b84b6edca997dacd600 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Tue, 15 Dec 2015 01:52:44 +0100
Subject: [PATCH 0238/1650] option to clear the history

---
 src/fe-common/core/command-history.c | 45 ++++++++++++++++++++++++----
 src/fe-common/core/command-history.h |  1 +
 src/fe-common/core/fe-windows.c      |  7 ++++-
 src/fe-common/core/fe-windows.h      |  1 +
 src/fe-common/core/window-commands.c | 21 +++++++++++--
 5 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/src/fe-common/core/command-history.c b/src/fe-common/core/command-history.c
index f9c3884c..9f46ee99 100644
--- a/src/fe-common/core/command-history.c
+++ b/src/fe-common/core/command-history.c
@@ -33,6 +33,7 @@
 static HISTORY_REC *global_history;
 static int window_history;
 static GSList *histories;
+static HISTORY_REC *last_cleared_history;
 
 void command_history_add(HISTORY_REC *history, const char *text)
 {
@@ -41,6 +42,13 @@ void command_history_add(HISTORY_REC *history, const char *text)
 	g_return_if_fail(history != NULL);
 	g_return_if_fail(text != NULL);
 
+	if (last_cleared_history == history) {
+		last_cleared_history = NULL;
+		return; /* ignore this history addition, we just
+			   cleared it */
+	}
+	last_cleared_history = NULL;
+
 	link = g_list_last(history->list);
 	if (link != NULL && g_strcmp0(link->data, text) == 0)
 	  return; /* same as previous entry */
@@ -94,13 +102,13 @@ HISTORY_REC *command_history_current(WINDOW_REC *window)
 	if (window == NULL)
 		return global_history;
 
-	if (window_history)
-		return window->history;
-
 	rec = command_history_find_name(window->history_name);
 	if (rec != NULL)
 		return rec;
 
+	if (window_history)
+		return window->history;
+
 	return global_history;
 }
 
@@ -178,6 +186,18 @@ HISTORY_REC *command_history_create(const char *name)
 	return rec;
 }
 
+void command_history_clear(HISTORY_REC *history)
+{
+	g_return_if_fail(history != NULL);
+
+	command_history_clear_pos_func(history, NULL);
+	g_list_foreach(history->list, (GFunc) g_free, NULL);
+	g_list_free(history->list);
+	history->list = NULL;
+	history->lines = 0;
+	last_cleared_history = history;
+}
+
 void command_history_destroy(HISTORY_REC *history)
 {
 	g_return_if_fail(history != NULL);
@@ -186,9 +206,8 @@ void command_history_destroy(HISTORY_REC *history)
 	g_return_if_fail(history->refcount == 0);
 
 	histories = g_slist_remove(histories, history);
-
-	g_list_foreach(history->list, (GFunc) g_free, NULL);
-	g_list_free(history->list);
+	command_history_clear(history);
+	last_cleared_history = NULL; /* was destroyed */
 
 	g_free_not_null(history->name);
 	g_free(history);
@@ -229,6 +248,18 @@ static void sig_window_destroyed(WINDOW_REC *window)
 	g_free_not_null(window->history_name);
 }
 
+static void sig_window_history_cleared(WINDOW_REC *window, const char *name) {
+	HISTORY_REC *history;
+
+	if (name == NULL || *name == '\0') {
+		history = command_history_current(window);
+	} else {
+		history = command_history_find_name(name);
+	}
+
+	command_history_clear(history);
+}
+
 static void sig_window_history_changed(WINDOW_REC *window, const char *oldname)
 {
 	command_history_link(window->history_name);
@@ -279,6 +310,7 @@ void command_history_init(void)
 	signal_add("window created", (SIGNAL_FUNC) sig_window_created);
 	signal_add("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
 	signal_add("window history changed", (SIGNAL_FUNC) sig_window_history_changed);
+	signal_add_last("window history cleared", (SIGNAL_FUNC) sig_window_history_cleared);
 	signal_add("setup changed", (SIGNAL_FUNC) read_settings);
 }
 
@@ -287,6 +319,7 @@ void command_history_deinit(void)
 	signal_remove("window created", (SIGNAL_FUNC) sig_window_created);
 	signal_remove("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
 	signal_remove("window history changed", (SIGNAL_FUNC) sig_window_history_changed);
+	signal_remove("window history cleared", (SIGNAL_FUNC) sig_window_history_cleared);
 	signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
 
 	command_history_destroy(global_history);
diff --git a/src/fe-common/core/command-history.h b/src/fe-common/core/command-history.h
index 7b76246b..a572216b 100644
--- a/src/fe-common/core/command-history.h
+++ b/src/fe-common/core/command-history.h
@@ -28,6 +28,7 @@ const char *command_history_next(WINDOW_REC *window, const char *text);
 void command_history_clear_pos(WINDOW_REC *window);
 
 HISTORY_REC *command_history_create(const char *name);
+void command_history_clear(HISTORY_REC *history);
 void command_history_destroy(HISTORY_REC *history);
 void command_history_link(const char *name);
 void command_history_unlink(const char *name);
diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c
index 1049137f..46c1593b 100644
--- a/src/fe-common/core/fe-windows.c
+++ b/src/fe-common/core/fe-windows.c
@@ -229,11 +229,16 @@ void window_set_history(WINDOW_REC *window, const char *name)
 	else
 		window->history_name = g_strdup(name);
 
-	signal_emit("window history changed", 1, window, oldname);
+	signal_emit("window history changed", 2, window, oldname);
 
 	g_free_not_null(oldname);
 }
 
+void window_clear_history(WINDOW_REC *window, const char *name)
+{
+	signal_emit("window history cleared", 2, window, name);
+}
+
 void window_set_level(WINDOW_REC *window, int level)
 {
 	g_return_if_fail(window != NULL);
diff --git a/src/fe-common/core/fe-windows.h b/src/fe-common/core/fe-windows.h
index 613f15f8..32d6cfcd 100644
--- a/src/fe-common/core/fe-windows.h
+++ b/src/fe-common/core/fe-windows.h
@@ -66,6 +66,7 @@ void window_change_server(WINDOW_REC *window, void *server);
 void window_set_refnum(WINDOW_REC *window, int refnum);
 void window_set_name(WINDOW_REC *window, const char *name);
 void window_set_history(WINDOW_REC *window, const char *name);
+void window_clear_history(WINDOW_REC *window, const char *name);
 void window_set_level(WINDOW_REC *window, int level);
 void window_set_immortal(WINDOW_REC *window, int immortal);
 
diff --git a/src/fe-common/core/window-commands.c b/src/fe-common/core/window-commands.c
index c6ab68c0..e5005144 100644
--- a/src/fe-common/core/window-commands.c
+++ b/src/fe-common/core/window-commands.c
@@ -33,6 +33,7 @@
 #include "window-items.h"
 #include "windows-layout.h"
 #include "printtext.h"
+#include "command-history.h"
 
 static void window_print_binds(WINDOW_REC *win)
 {
@@ -615,10 +616,25 @@ static void cmd_window_name(const char *data)
 	}
 }
 
-/* SYNTAX: WINDOW HISTORY  */
+/* SYNTAX: WINDOW HISTORY [-clear]  */
 void cmd_window_history(const char *data)
 {
-	window_set_history(active_win, data);
+	GHashTable *optlist;
+        char *name;
+	void *free_arg;
+
+	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS,
+			    "window history", &optlist, &name))
+		return;
+
+	if (g_hash_table_lookup(optlist, "clear") != NULL) {
+		signal_continue(1, data);
+		window_clear_history(active_win, name);
+	} else {
+		window_set_history(active_win, name);
+	}
+
+	cmd_params_free(free_arg);
 }
 
 /* we're moving the first window to last - move the first contiguous block
@@ -883,6 +899,7 @@ void window_commands_init(void)
 	command_set_options("window number", "sticky");
 	command_set_options("window server", "sticky unsticky");
 	command_set_options("window theme", "delete");
+	command_set_options("window history", "clear");
 }
 
 void window_commands_deinit(void)

From 653fd590aff1d2f602ceef999b3df2719e0835b1 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Sun, 13 Dec 2015 12:35:27 +0100
Subject: [PATCH 0239/1650] add new authors since 0.8.17

---
 AUTHORS | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index d2cb58c0..dc8e578c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -11,6 +11,8 @@ Irssi staff (current maintainers) :
   Jilles Tjoelker (jilles)
   Alexander Færøy (ahf)
   Jase Thew (bazerka)
+  dequis (dx)
+  Ailin Nemui (Nei)
 
 Former developers:
 
@@ -24,6 +26,7 @@ Large feature patches by:
   Heikki Orsila : DCC SEND queueing
   Mark Trumbull : DCC SERVER
   Francesco Fracassi : Passive DCC
+  Giuseppe (The Lemon Man)
 
 Other patches (grep for "patch" in ChangeLog) by:
 
@@ -78,6 +81,20 @@ Other patches (grep for "patch" in ChangeLog) by:
   Ismael Luceno
   Thomas Karpiniec
   Svante Kvarnström
-  Ailin Nemui (Nei)
   Tom Feist (shabble)
-  Sebastian Thorarensen
+  Sebastian Thorarensen (Sebban)
+  Hans Nielsen
+  Jari Matilainen (vague)
+  Thibault B (isundil)
+  kyak
+  Vesa Pirila (Lohhari)
+  Haw Loeung
+  François Revol (mmuman)
+  blha303
+  Guillaume Brogi (guiniol)
+  Adam-
+  Robert C Jensen
+  Paul Johnson
+  mauke
+  KindOne
+  Fabian Kurz

From ab809d8d2a9cfb3f0d879c098f2d2d88ce60d3fe Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Sun, 13 Dec 2015 14:14:41 +0100
Subject: [PATCH 0240/1650] list NEWS since 0.8.17

---
 NEWS | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 51 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index 511f495a..c37129bb 100644
--- a/NEWS
+++ b/NEWS
@@ -1,9 +1,57 @@
-v0.8.18-head 2014-XX-YY  The Irssi team 
-	+ Garbage Collection support has been removed. This will hardly have any
+v0.8.18-rc1 2015-12-15  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
+	  version.
+	* The signature of "message private" has been changed to
+	      5: server, message, nick, address, target
+	  in order to support "self messages". Module authors should
+	  implement this change if they are using this signal.
+	* Removing networks will now remove all attached servers and channels
+          (#45).
+	* /proxy command has been renamed to /irssiproxy
+	* sb_search has been moved to scripts.irssi.org
+	* WIN32 has been completely removed (it had not been working and is
+          lacking a maintainer.)
+	* Garbage Collection support has been removed. This will hardly have any
 	  effect for anyone given that it has been unsupported for several years.
-	+ Disable SSLv3 due to the POODLE vulnerability.
+	+ CAP SASL PLAIN login is now supported natively.
+	+ Paste bracket markers can be requested from terminal with
+	      /set paste_use_bracketed_mode on
+	+ "Self messages" generated by some bouncers can now be received in the
+	  proper window.
 	+ Try to split long lines on spaces to avoid words being splitted. Adds
 	  a new option: 'split_line_on_space' which defaults to on.
+	+ Add setting hilight_nick_matches_everywhere (#56).
+	+ The config parser is more robust and prints out better diagnostics on
+	  incorrect config files.
+	+ Ctrl+^ (FS#721) and Ctrl+J can now be bound.
+	+ Command history can be cleared with /window history -clear
+	+ /hilight -mask -line is now supported (FS#275).
+	+ CHANTYPES are now supported.
+	+ Improved reload speed of ignores.
+	+ Add -date feature to /lastlog
+	+ irssiproxy can be more easily enabled and disabled.
+	+ Expando for hostname (FS#829).
+	+ UNIX sockets can now also be specified in the config file.
+	+ Disable SSLv3 due to the POODLE vulnerability.
+	+ SSL ciphers can now be specified per server.
+	+ Added SNI support for SSL.
+	- irssiproxy (BNC) module now uses correct line endings.
+	- Fix missing lines on large pastes (FS#905).
+	- Correctly preserve STATUSMSG prefixes (#291).
+	- Fix infinite recursion in key bindings (FS#817).
+	- Fix incomplete awaylog caused by buffering.
+	- Fix calculation of UTF-8 string length display in some cases.
+	- Fix some Perl warnings related to @ISA.
+	- EXEC windowitems now get proper references on the Perl side.
+	- Incremental help file improvements.
+	- ANSI attributes are now properly reset.
+	- Fixed regression where text would blink when terminal lacks color
+          support.
+	- Permit the usage of Freenode extban syntax in /ban (#150)
+	- Fixed regression in scriptassist on unload of scripts.
+	- Fixed regression in -actcolor %n
 
 v0.8.17 2014-10-11  The Irssi team 
 	+ Document that SSL connections aren't properly handled during /UPGRADE. See Github PR #39.

From 77143aee7dcff85f0b8656543c185a9e6a8131bb Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Sun, 13 Dec 2015 14:17:33 +0100
Subject: [PATCH 0241/1650] remove mention of ./autogen.sh from releases
 INSTALL

---
 INSTALL | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/INSTALL b/INSTALL
index 234c6cf6..a83a6c76 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,8 +11,7 @@ To compile irssi you need:
 
 For most people, this should work just fine:
 
- ./autogen.sh     (for people who just cloned the repository)
- ./configure      (if this script already exists, skip ./autogen.sh)
+ ./configure
  make
  su
  make install     (not _really_ required except for perl support)

From d495111bde29796430e34832f15025f3708a7166 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Tue, 15 Dec 2015 10:59:23 +0100
Subject: [PATCH 0242/1650] tag as 0.8.18-beta1

---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index c0efd5e3..92ca04ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(irssi, 0.8.18-head)
+AC_INIT(irssi, 0.8.18-beta1)
 AC_CONFIG_SRCDIR([src])
 AC_CONFIG_AUX_DIR(build-aux)
 AC_PREREQ(2.50)

From 74eb556c504271129f44268870d34c011804d7e4 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Sun, 13 Dec 2015 12:35:27 +0100
Subject: [PATCH 0243/1650] add new authors since 0.8.17

---
 AUTHORS | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index d2cb58c0..dc8e578c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -11,6 +11,8 @@ Irssi staff (current maintainers) :
   Jilles Tjoelker (jilles)
   Alexander Færøy (ahf)
   Jase Thew (bazerka)
+  dequis (dx)
+  Ailin Nemui (Nei)
 
 Former developers:
 
@@ -24,6 +26,7 @@ Large feature patches by:
   Heikki Orsila : DCC SEND queueing
   Mark Trumbull : DCC SERVER
   Francesco Fracassi : Passive DCC
+  Giuseppe (The Lemon Man)
 
 Other patches (grep for "patch" in ChangeLog) by:
 
@@ -78,6 +81,20 @@ Other patches (grep for "patch" in ChangeLog) by:
   Ismael Luceno
   Thomas Karpiniec
   Svante Kvarnström
-  Ailin Nemui (Nei)
   Tom Feist (shabble)
-  Sebastian Thorarensen
+  Sebastian Thorarensen (Sebban)
+  Hans Nielsen
+  Jari Matilainen (vague)
+  Thibault B (isundil)
+  kyak
+  Vesa Pirila (Lohhari)
+  Haw Loeung
+  François Revol (mmuman)
+  blha303
+  Guillaume Brogi (guiniol)
+  Adam-
+  Robert C Jensen
+  Paul Johnson
+  mauke
+  KindOne
+  Fabian Kurz

From 64463933fdb923cdc55fcd105c8e35d61546e62e Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Sun, 13 Dec 2015 14:14:41 +0100
Subject: [PATCH 0244/1650] list NEWS since 0.8.17

---
 NEWS | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index 511f495a..8db80f80 100644
--- a/NEWS
+++ b/NEWS
@@ -1,9 +1,52 @@
-v0.8.18-head 2014-XX-YY  The Irssi team 
-	+ Garbage Collection support has been removed. This will hardly have any
+v0.8.18-head 2016-xx-xx  The Irssi team 
+	* The signature of "message private" has been changed to
+	      5: server, message, nick, address, target
+	  in order to support "self messages". Module authors should
+	  implement this change if they are using this signal.
+	* Removing networks will now remove all attached servers and channels
+          (#45).
+	* The proxy module now has an /irssiproxy command.
+	* sb_search has been moved to scripts.irssi.org
+	* WIN32 has been completely removed (it had not been working and is
+          lacking a maintainer.)
+	* Garbage Collection support has been removed. This will hardly have any
 	  effect for anyone given that it has been unsupported for several years.
-	+ Disable SSLv3 due to the POODLE vulnerability.
+	+ CAP SASL PLAIN login is now supported natively.
+	+ Paste bracket markers can be requested from terminal with
+	      /set paste_use_bracketed_mode on
+	+ "Self messages" generated by some bouncers can now be received in the
+	  proper window.
 	+ Try to split long lines on spaces to avoid words being splitted. Adds
 	  a new option: 'split_line_on_space' which defaults to on.
+	+ Add setting hilight_nick_matches_everywhere (#56).
+	+ The config parser is more robust and prints out better diagnostics on
+	  incorrect config files.
+	+ Ctrl+^ (FS#721) and Ctrl+J can now be bound.
+	+ /hilight -mask -line is now supported (FS#275).
+	+ CHANTYPES are now supported.
+	+ Improved reload speed of ignores.
+	+ Add -date feature to /lastlog
+	+ irssiproxy can be more easily enabled and disabled.
+	+ Expando for hostname (FS#829).
+	+ UNIX sockets can now also be specified in the config file.
+	+ Disable SSLv3 due to the POODLE vulnerability.
+	+ SSL ciphers can now be specified per server.
+	+ Added SNI support for SSL.
+	- irssiproxy (BNC) module now uses correct line endings.
+	- Fix missing lines on large pastes (FS#905).
+	- Correctly preserve STATUSMSG prefixes (#291).
+	- Fix infinite recursion in key bindings (FS#817).
+	- Fix incomplete awaylog caused by buffering.
+	- Fix calculation of UTF-8 string length display in some cases.
+	- Fix some Perl warnings related to @ISA.
+	- EXEC windowitems now get proper references on the Perl side.
+	- Incremental help file improvements.
+	- ANSI attributes are now properly reset.
+	- Fixed regression where text would blink when terminal lacks color
+          support.
+	- Permit the usage of Freenode extban syntax in /ban (#150)
+	- Fixed regression in scriptassist on unload of scripts.
+	- Fixed regression in -actcolor %n
 
 v0.8.17 2014-10-11  The Irssi team 
 	+ Document that SSL connections aren't properly handled during /UPGRADE. See Github PR #39.

From f6d4b11079e0e8c2619989e3550a8ebd161eb1ae Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Tue, 22 Dec 2015 00:51:57 +0100
Subject: [PATCH 0245/1650] correct incorrect pre-release tag in NEWS

---
 NEWS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index c37129bb..6155f7bd 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-v0.8.18-rc1 2015-12-15  The Irssi team 
+v0.8.18-beta1 2015-12-15  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

From c6a85721a6e9d5a6f67f76f0062c750146c6805f Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Mon, 28 Dec 2015 00:07:42 +0100
Subject: [PATCH 0246/1650] keep track of address in text_dest for hilight
 purposes

---
 src/fe-common/core/fe-messages.c  | 10 ++++------
 src/fe-common/core/formats.c      |  2 --
 src/fe-common/core/formats.h      |  5 ++---
 src/fe-common/core/hilight-text.c |  7 ++++---
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c
index e06a4571..3240fd10 100644
--- a/src/fe-common/core/fe-messages.c
+++ b/src/fe-common/core/fe-messages.c
@@ -175,7 +175,6 @@ 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;
-	int match_beg = 0, match_end = 0;
 
 	/* NOTE: this may return NULL if some channel is just closed with
 	   /WINDOW CLOSE and server still sends the few last messages */
@@ -188,8 +187,8 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
 		nick_match_msg(chanrec, msg, server->nick) :
 		nick_match_msg_everywhere(chanrec, msg, server->nick);
 	hilight = for_me ? NULL :
-		hilight_match(server, target, nick, address, MSGLEVEL_PUBLIC, msg, &match_beg, &match_end);
-	color = (hilight == NULL || !hilight->nick) ? NULL : hilight_get_color(hilight);
+		hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC, msg);
+	color = (hilight == NULL) ? NULL : hilight_get_color(hilight);
 
 	print_channel = chanrec == NULL ||
 		!window_item_is_active((WI_ITEM_REC *) chanrec);
@@ -217,9 +216,8 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
 
 	TEXT_DEST_REC dest;
 	format_create_dest(&dest, server, target, level, NULL);
-	dest.hilight = hilight;
-	dest.match_beg = match_beg;
-	dest.match_end = match_end;
+	dest.address = address;
+	dest.nick = nick;
 	if (color != NULL) {
 		/* highlighted nick */
 		hilight_update_text_dest(&dest,hilight);
diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c
index b95b3966..ccf48394 100644
--- a/src/fe-common/core/formats.c
+++ b/src/fe-common/core/formats.c
@@ -416,8 +416,6 @@ void format_create_dest_tag(TEXT_DEST_REC *dest, void *server,
 	dest->server_tag = server != NULL ? SERVER(server)->tag : server_tag;
 	dest->target = target;
 	dest->level = level;
-	dest->match_beg = 0;
-	dest->match_end = 0;
 	dest->window = window != NULL ? window :
 		window_find_closest(server, target, level);
 }
diff --git a/src/fe-common/core/formats.h b/src/fe-common/core/formats.h
index a4b26852..8efd204c 100644
--- a/src/fe-common/core/formats.h
+++ b/src/fe-common/core/formats.h
@@ -52,11 +52,10 @@ typedef struct _TEXT_DEST_REC {
 	SERVER_REC *server;
         const char *server_tag; /* if server is non-NULL, must be server->tag */
 	const char *target;
+	const char *nick;
+	const char *address;
 	int level;
 
-	HILIGHT_REC *hilight;
-	int match_beg;
-	int match_end;
 	int hilight_priority;
 	char *hilight_color;
         int flags;
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index 2c0075ec..b746f636 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -325,9 +325,10 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text,
 	if (dest->level & MSGLEVEL_NOHILIGHT)
 		return;
 
-	hilight_start = dest->match_beg;
-	hilight_end = dest->match_end;
-	hilight = dest->hilight;
+	hilight_start = hilight_end = 0;
+	hilight = hilight_match(dest->server, dest->target, dest->nick,
+				dest->address, dest->level, stripped,
+				&hilight_start, &hilight_end);
 
 	if (hilight == NULL)
 		return;

From 7cc85b9427887c4f77b8a5706b148371e713828b Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Mon, 28 Dec 2015 00:07:42 +0100
Subject: [PATCH 0247/1650] keep track of address in text_dest for hilight
 purposes

---
 src/fe-common/core/fe-messages.c  | 10 ++++------
 src/fe-common/core/formats.c      |  2 --
 src/fe-common/core/formats.h      |  5 ++---
 src/fe-common/core/hilight-text.c |  7 ++++---
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c
index e06a4571..3240fd10 100644
--- a/src/fe-common/core/fe-messages.c
+++ b/src/fe-common/core/fe-messages.c
@@ -175,7 +175,6 @@ 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;
-	int match_beg = 0, match_end = 0;
 
 	/* NOTE: this may return NULL if some channel is just closed with
 	   /WINDOW CLOSE and server still sends the few last messages */
@@ -188,8 +187,8 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
 		nick_match_msg(chanrec, msg, server->nick) :
 		nick_match_msg_everywhere(chanrec, msg, server->nick);
 	hilight = for_me ? NULL :
-		hilight_match(server, target, nick, address, MSGLEVEL_PUBLIC, msg, &match_beg, &match_end);
-	color = (hilight == NULL || !hilight->nick) ? NULL : hilight_get_color(hilight);
+		hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC, msg);
+	color = (hilight == NULL) ? NULL : hilight_get_color(hilight);
 
 	print_channel = chanrec == NULL ||
 		!window_item_is_active((WI_ITEM_REC *) chanrec);
@@ -217,9 +216,8 @@ static void sig_message_public(SERVER_REC *server, const char *msg,
 
 	TEXT_DEST_REC dest;
 	format_create_dest(&dest, server, target, level, NULL);
-	dest.hilight = hilight;
-	dest.match_beg = match_beg;
-	dest.match_end = match_end;
+	dest.address = address;
+	dest.nick = nick;
 	if (color != NULL) {
 		/* highlighted nick */
 		hilight_update_text_dest(&dest,hilight);
diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c
index b95b3966..ccf48394 100644
--- a/src/fe-common/core/formats.c
+++ b/src/fe-common/core/formats.c
@@ -416,8 +416,6 @@ void format_create_dest_tag(TEXT_DEST_REC *dest, void *server,
 	dest->server_tag = server != NULL ? SERVER(server)->tag : server_tag;
 	dest->target = target;
 	dest->level = level;
-	dest->match_beg = 0;
-	dest->match_end = 0;
 	dest->window = window != NULL ? window :
 		window_find_closest(server, target, level);
 }
diff --git a/src/fe-common/core/formats.h b/src/fe-common/core/formats.h
index a4b26852..8efd204c 100644
--- a/src/fe-common/core/formats.h
+++ b/src/fe-common/core/formats.h
@@ -52,11 +52,10 @@ typedef struct _TEXT_DEST_REC {
 	SERVER_REC *server;
         const char *server_tag; /* if server is non-NULL, must be server->tag */
 	const char *target;
+	const char *nick;
+	const char *address;
 	int level;
 
-	HILIGHT_REC *hilight;
-	int match_beg;
-	int match_end;
 	int hilight_priority;
 	char *hilight_color;
         int flags;
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index 2c0075ec..b746f636 100644
--- a/src/fe-common/core/hilight-text.c
+++ b/src/fe-common/core/hilight-text.c
@@ -325,9 +325,10 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text,
 	if (dest->level & MSGLEVEL_NOHILIGHT)
 		return;
 
-	hilight_start = dest->match_beg;
-	hilight_end = dest->match_end;
-	hilight = dest->hilight;
+	hilight_start = hilight_end = 0;
+	hilight = hilight_match(dest->server, dest->target, dest->nick,
+				dest->address, dest->level, stripped,
+				&hilight_start, &hilight_end);
 
 	if (hilight == NULL)
 		return;

From 609f3ba6c2db4f04e1e11304459d4fc42babd8ff Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Sun, 3 Jan 2016 19:49:18 +0100
Subject: [PATCH 0248/1650] Clean up the ignore_find API to make it more
 powerful.

This way we prevent the creation of duplicate ignores since the old code
skipped the ignore_find call when a pattern was specified.
It should also cover all the cases where the ignores would be wrongly
overwritten, such as the case outlined in #78.
---
 src/core/ignore.c              | 28 ++++++++++++++++------------
 src/core/ignore.h              |  9 +++++++--
 src/fe-common/core/fe-ignore.c |  8 ++++----
 src/irc/flood/autoignore.c     |  2 +-
 4 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/src/core/ignore.c b/src/core/ignore.c
index fd3c8a38..ee9e180d 100644
--- a/src/core/ignore.c
+++ b/src/core/ignore.c
@@ -186,15 +186,8 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host,
         return ignore_check_replies(chanrec, text, level);
 }
 
-IGNORE_REC *ignore_find(const char *servertag, const char *mask,
-		char **channels)
-{
-	return ignore_find_noact(servertag, mask, channels, 0);
-}
-
-
-IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask,
-		char **channels, int noact)
+IGNORE_REC *ignore_find(const char *servertag, const char *mask, const char *pattern,
+		char **channels, const int flags)
 {
 	GSList *tmp;
 	char **chan;
@@ -216,18 +209,29 @@ IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask,
 				continue;
 		}
 
-		if (noact && (rec->level & MSGLEVEL_NO_ACT) == 0)
+		if ((flags & IGNORE_FIND_NOACT) && (rec->level & MSGLEVEL_NO_ACT) == 0)
 			continue;
 
-		if (!noact && (rec->level & MSGLEVEL_NO_ACT) != 0)
+		if (!(flags & IGNORE_FIND_NOACT) && (rec->level & MSGLEVEL_NO_ACT) != 0)
 			continue;
 
 		if ((rec->mask == NULL && mask != NULL) ||
-		    (rec->mask != NULL && mask == NULL)) continue;
+		    (rec->mask != NULL && mask == NULL))
+			continue;
 
 		if (rec->mask != NULL && g_ascii_strcasecmp(rec->mask, mask) != 0)
 			continue;
 
+		/* match the pattern too if requested */
+		if (flags & IGNORE_FIND_PATTERN) {
+			if ((rec->pattern == NULL && pattern != NULL) ||
+			    (rec->pattern != NULL && pattern == NULL))
+				continue;
+
+			if (rec->pattern != NULL && g_ascii_strcasecmp(rec->pattern, pattern) != 0)
+				continue;
+		}
+
 		if ((channels == NULL && rec->channels == NULL))
 			return rec; /* no channels - ok */
 
diff --git a/src/core/ignore.h b/src/core/ignore.h
index 46025d4c..0901e795 100644
--- a/src/core/ignore.h
+++ b/src/core/ignore.h
@@ -31,8 +31,13 @@ extern GSList *ignores;
 int ignore_check(SERVER_REC *server, const char *nick, const char *host,
 		 const char *channel, const char *text, int level);
 
-IGNORE_REC *ignore_find(const char *servertag, const char *mask, char **channels);
-IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, char **channels, int noact);
+enum {
+	IGNORE_FIND_PATTERN = 0x01, // Match the pattern
+	IGNORE_FIND_NOACT   = 0x02, // Exclude the targets with NOACT level
+};
+
+IGNORE_REC *ignore_find(const char *servertag, const char *mask, const char *pattern,
+		char **channels, const int flags);
 
 void ignore_add_rec(IGNORE_REC *rec);
 void ignore_update_rec(IGNORE_REC *rec);
diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c
index d2f9de27..2799e15f 100644
--- a/src/fe-common/core/fe-ignore.c
+++ b/src/fe-common/core/fe-ignore.c
@@ -158,8 +158,8 @@ static void cmd_ignore(const char *data)
 	channels = (chanarg == NULL || *chanarg == '\0') ? NULL :
 		g_strsplit(chanarg, ",", -1);
 
-	rec = patternarg != NULL ? NULL: ignore_find_noact(servertag, mask, channels,
-			(level & MSGLEVEL_NO_ACT));
+	rec = ignore_find(servertag, mask, patternarg, channels,
+			  IGNORE_FIND_PATTERN | ((level & MSGLEVEL_NO_ACT) ? IGNORE_FIND_NOACT : 0));
 	new_ignore = rec == NULL;
 
 	if (rec == NULL) {
@@ -237,9 +237,9 @@ static void cmd_unignore(const char *data)
 			chans[0] = mask;
 			mask = NULL;
 		}
-		rec = ignore_find_noact("*", mask, (char **) chans, 0);
+		rec = ignore_find("*", mask, NULL, (char **) chans, 0);
 		if (rec == NULL) {
-			rec = ignore_find_noact("*", mask, (char **) chans, 1);
+			rec = ignore_find("*", mask, NULL, (char **) chans, IGNORE_FIND_NOACT);
 		}
 	}
 
diff --git a/src/irc/flood/autoignore.c b/src/irc/flood/autoignore.c
index 250a1fe8..4708cb03 100644
--- a/src/irc/flood/autoignore.c
+++ b/src/irc/flood/autoignore.c
@@ -66,7 +66,7 @@ static void sig_flood(IRC_SERVER_REC *server, const char *nick, const char *host
 
         mask = g_strdup_printf("%s!%s", nick, host);
 	if (level & check_level) {
-		rec = ignore_find(server->tag, mask, NULL);
+		rec = ignore_find(server->tag, mask, NULL, NULL, 0);
 		if (rec == NULL)
 			autoignore_add(server, mask, level);
 		else

From dbee606c60c4d8d7c6e5cabd1241fc182ae6c4a3 Mon Sep 17 00:00:00 2001
From: LemonBoy 
Date: Sun, 3 Jan 2016 21:19:46 +0100
Subject: [PATCH 0249/1650] Don't break the API.

Have a ignore_find_full method that is the one that all the new code
should be using and provide some working stubs for ignore_find and
ignore_find_noact.
---
 src/core/ignore.c              | 12 +++++++++++-
 src/core/ignore.h              |  9 +++++++--
 src/fe-common/core/fe-ignore.c |  6 +++---
 src/irc/flood/autoignore.c     |  2 +-
 4 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/src/core/ignore.c b/src/core/ignore.c
index ee9e180d..8d5a27c2 100644
--- a/src/core/ignore.c
+++ b/src/core/ignore.c
@@ -186,7 +186,7 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host,
         return ignore_check_replies(chanrec, text, level);
 }
 
-IGNORE_REC *ignore_find(const char *servertag, const char *mask, const char *pattern,
+IGNORE_REC *ignore_find_full(const char *servertag, const char *mask, const char *pattern,
 		char **channels, const int flags)
 {
 	GSList *tmp;
@@ -257,6 +257,16 @@ IGNORE_REC *ignore_find(const char *servertag, const char *mask, const char *pat
 	return NULL;
 }
 
+IGNORE_REC *ignore_find(const char *servertag, const char *mask, char **channels)
+{
+	return ignore_find_full(servertag, mask, NULL, channels, 0);
+}
+
+IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, char **channels, int noact)
+{
+	return ignore_find_full(servertag, mask, NULL, channels, IGNORE_FIND_NOACT);
+}
+
 static void ignore_set_config(IGNORE_REC *rec)
 {
 	CONFIG_NODE *node;
diff --git a/src/core/ignore.h b/src/core/ignore.h
index 0901e795..f889740f 100644
--- a/src/core/ignore.h
+++ b/src/core/ignore.h
@@ -36,8 +36,13 @@ enum {
 	IGNORE_FIND_NOACT   = 0x02, // Exclude the targets with NOACT level
 };
 
-IGNORE_REC *ignore_find(const char *servertag, const char *mask, const char *pattern,
-		char **channels, const int flags);
+IGNORE_REC *ignore_find_full (const char *servertag, const char *mask, const char *pattern,
+                char **channels, const int flags);
+
+// Convenience wrappers around ignore_find_full, for compatibility purpose
+
+IGNORE_REC *ignore_find(const char *servertag, const char *mask, char **channels);
+IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, char **channels, int noact);
 
 void ignore_add_rec(IGNORE_REC *rec);
 void ignore_update_rec(IGNORE_REC *rec);
diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c
index 2799e15f..a809ac91 100644
--- a/src/fe-common/core/fe-ignore.c
+++ b/src/fe-common/core/fe-ignore.c
@@ -158,7 +158,7 @@ static void cmd_ignore(const char *data)
 	channels = (chanarg == NULL || *chanarg == '\0') ? NULL :
 		g_strsplit(chanarg, ",", -1);
 
-	rec = ignore_find(servertag, mask, patternarg, channels,
+	rec = ignore_find_full(servertag, mask, patternarg, channels,
 			  IGNORE_FIND_PATTERN | ((level & MSGLEVEL_NO_ACT) ? IGNORE_FIND_NOACT : 0));
 	new_ignore = rec == NULL;
 
@@ -237,9 +237,9 @@ static void cmd_unignore(const char *data)
 			chans[0] = mask;
 			mask = NULL;
 		}
-		rec = ignore_find("*", mask, NULL, (char **) chans, 0);
+		rec = ignore_find_full("*", mask, NULL, (char **) chans, 0);
 		if (rec == NULL) {
-			rec = ignore_find("*", mask, NULL, (char **) chans, IGNORE_FIND_NOACT);
+			rec = ignore_find_full("*", mask, NULL, (char **) chans, IGNORE_FIND_NOACT);
 		}
 	}
 
diff --git a/src/irc/flood/autoignore.c b/src/irc/flood/autoignore.c
index 4708cb03..86ff3ec5 100644
--- a/src/irc/flood/autoignore.c
+++ b/src/irc/flood/autoignore.c
@@ -66,7 +66,7 @@ static void sig_flood(IRC_SERVER_REC *server, const char *nick, const char *host
 
         mask = g_strdup_printf("%s!%s", nick, host);
 	if (level & check_level) {
-		rec = ignore_find(server->tag, mask, NULL, NULL, 0);
+		rec = ignore_find_full(server->tag, mask, NULL, NULL, 0);
 		if (rec == NULL)
 			autoignore_add(server, mask, level);
 		else

From 837e03bd8f1be71ca26e3c2581b5444dcb5fe73f Mon Sep 17 00:00:00 2001
From: Lukas Mai 
Date: Wed, 6 Jan 2016 12:45:18 +0100
Subject: [PATCH 0250/1650] irssiproxy: avoid using pointer after freeing it

---
 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 dcc94e6b..5dc9a704 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -681,8 +681,8 @@ static void read_settings(void)
 	while (add_listens != NULL) {
 		rec = add_listens->data;
 		add_listen(rec->ircnet, rec->port);
+		add_listens = g_slist_remove(add_listens, rec);
 		g_free(rec);
-		add_listens = g_slist_remove(add_listens, add_listens->data);
 	}
 
 	g_strfreev(ports);

From cfb6123a7ab56e12136711a7e088424c9f68fd26 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Wed, 6 Jan 2016 17:25:53 +0100
Subject: [PATCH 0251/1650] forward ABI to perl modules

---
 src/perl/module.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/perl/module.h b/src/perl/module.h
index 2fd15137..3cbdf3d5 100644
--- a/src/perl/module.h
+++ b/src/perl/module.h
@@ -17,4 +17,4 @@ extern PerlInterpreter *my_perl; /* must be called my_perl or some perl implemen
 
 /* Change this every time when some API changes between irssi's perl module
    (or irssi itself) and irssi's perl libraries. */
-#define IRSSI_PERL_API_VERSION 20011214
+#define IRSSI_PERL_API_VERSION (20011214 + IRSSI_ABI_VERSION)

From 4659cea65a663b11f3cc16e1d03c9955a4135238 Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Tue, 15 Dec 2015 01:52:44 +0100
Subject: [PATCH 0252/1650] option to clear the history

---
 src/fe-common/core/command-history.c | 45 ++++++++++++++++++++++++----
 src/fe-common/core/command-history.h |  1 +
 src/fe-common/core/fe-windows.c      |  7 ++++-
 src/fe-common/core/fe-windows.h      |  1 +
 src/fe-common/core/window-commands.c | 21 +++++++++++--
 5 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/src/fe-common/core/command-history.c b/src/fe-common/core/command-history.c
index f9c3884c..9f46ee99 100644
--- a/src/fe-common/core/command-history.c
+++ b/src/fe-common/core/command-history.c
@@ -33,6 +33,7 @@
 static HISTORY_REC *global_history;
 static int window_history;
 static GSList *histories;
+static HISTORY_REC *last_cleared_history;
 
 void command_history_add(HISTORY_REC *history, const char *text)
 {
@@ -41,6 +42,13 @@ void command_history_add(HISTORY_REC *history, const char *text)
 	g_return_if_fail(history != NULL);
 	g_return_if_fail(text != NULL);
 
+	if (last_cleared_history == history) {
+		last_cleared_history = NULL;
+		return; /* ignore this history addition, we just
+			   cleared it */
+	}
+	last_cleared_history = NULL;
+
 	link = g_list_last(history->list);
 	if (link != NULL && g_strcmp0(link->data, text) == 0)
 	  return; /* same as previous entry */
@@ -94,13 +102,13 @@ HISTORY_REC *command_history_current(WINDOW_REC *window)
 	if (window == NULL)
 		return global_history;
 
-	if (window_history)
-		return window->history;
-
 	rec = command_history_find_name(window->history_name);
 	if (rec != NULL)
 		return rec;
 
+	if (window_history)
+		return window->history;
+
 	return global_history;
 }
 
@@ -178,6 +186,18 @@ HISTORY_REC *command_history_create(const char *name)
 	return rec;
 }
 
+void command_history_clear(HISTORY_REC *history)
+{
+	g_return_if_fail(history != NULL);
+
+	command_history_clear_pos_func(history, NULL);
+	g_list_foreach(history->list, (GFunc) g_free, NULL);
+	g_list_free(history->list);
+	history->list = NULL;
+	history->lines = 0;
+	last_cleared_history = history;
+}
+
 void command_history_destroy(HISTORY_REC *history)
 {
 	g_return_if_fail(history != NULL);
@@ -186,9 +206,8 @@ void command_history_destroy(HISTORY_REC *history)
 	g_return_if_fail(history->refcount == 0);
 
 	histories = g_slist_remove(histories, history);
-
-	g_list_foreach(history->list, (GFunc) g_free, NULL);
-	g_list_free(history->list);
+	command_history_clear(history);
+	last_cleared_history = NULL; /* was destroyed */
 
 	g_free_not_null(history->name);
 	g_free(history);
@@ -229,6 +248,18 @@ static void sig_window_destroyed(WINDOW_REC *window)
 	g_free_not_null(window->history_name);
 }
 
+static void sig_window_history_cleared(WINDOW_REC *window, const char *name) {
+	HISTORY_REC *history;
+
+	if (name == NULL || *name == '\0') {
+		history = command_history_current(window);
+	} else {
+		history = command_history_find_name(name);
+	}
+
+	command_history_clear(history);
+}
+
 static void sig_window_history_changed(WINDOW_REC *window, const char *oldname)
 {
 	command_history_link(window->history_name);
@@ -279,6 +310,7 @@ void command_history_init(void)
 	signal_add("window created", (SIGNAL_FUNC) sig_window_created);
 	signal_add("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
 	signal_add("window history changed", (SIGNAL_FUNC) sig_window_history_changed);
+	signal_add_last("window history cleared", (SIGNAL_FUNC) sig_window_history_cleared);
 	signal_add("setup changed", (SIGNAL_FUNC) read_settings);
 }
 
@@ -287,6 +319,7 @@ void command_history_deinit(void)
 	signal_remove("window created", (SIGNAL_FUNC) sig_window_created);
 	signal_remove("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
 	signal_remove("window history changed", (SIGNAL_FUNC) sig_window_history_changed);
+	signal_remove("window history cleared", (SIGNAL_FUNC) sig_window_history_cleared);
 	signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
 
 	command_history_destroy(global_history);
diff --git a/src/fe-common/core/command-history.h b/src/fe-common/core/command-history.h
index 7b76246b..a572216b 100644
--- a/src/fe-common/core/command-history.h
+++ b/src/fe-common/core/command-history.h
@@ -28,6 +28,7 @@ const char *command_history_next(WINDOW_REC *window, const char *text);
 void command_history_clear_pos(WINDOW_REC *window);
 
 HISTORY_REC *command_history_create(const char *name);
+void command_history_clear(HISTORY_REC *history);
 void command_history_destroy(HISTORY_REC *history);
 void command_history_link(const char *name);
 void command_history_unlink(const char *name);
diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c
index 1049137f..46c1593b 100644
--- a/src/fe-common/core/fe-windows.c
+++ b/src/fe-common/core/fe-windows.c
@@ -229,11 +229,16 @@ void window_set_history(WINDOW_REC *window, const char *name)
 	else
 		window->history_name = g_strdup(name);
 
-	signal_emit("window history changed", 1, window, oldname);
+	signal_emit("window history changed", 2, window, oldname);
 
 	g_free_not_null(oldname);
 }
 
+void window_clear_history(WINDOW_REC *window, const char *name)
+{
+	signal_emit("window history cleared", 2, window, name);
+}
+
 void window_set_level(WINDOW_REC *window, int level)
 {
 	g_return_if_fail(window != NULL);
diff --git a/src/fe-common/core/fe-windows.h b/src/fe-common/core/fe-windows.h
index 613f15f8..32d6cfcd 100644
--- a/src/fe-common/core/fe-windows.h
+++ b/src/fe-common/core/fe-windows.h
@@ -66,6 +66,7 @@ void window_change_server(WINDOW_REC *window, void *server);
 void window_set_refnum(WINDOW_REC *window, int refnum);
 void window_set_name(WINDOW_REC *window, const char *name);
 void window_set_history(WINDOW_REC *window, const char *name);
+void window_clear_history(WINDOW_REC *window, const char *name);
 void window_set_level(WINDOW_REC *window, int level);
 void window_set_immortal(WINDOW_REC *window, int immortal);
 
diff --git a/src/fe-common/core/window-commands.c b/src/fe-common/core/window-commands.c
index c6ab68c0..e5005144 100644
--- a/src/fe-common/core/window-commands.c
+++ b/src/fe-common/core/window-commands.c
@@ -33,6 +33,7 @@
 #include "window-items.h"
 #include "windows-layout.h"
 #include "printtext.h"
+#include "command-history.h"
 
 static void window_print_binds(WINDOW_REC *win)
 {
@@ -615,10 +616,25 @@ static void cmd_window_name(const char *data)
 	}
 }
 
-/* SYNTAX: WINDOW HISTORY  */
+/* SYNTAX: WINDOW HISTORY [-clear]  */
 void cmd_window_history(const char *data)
 {
-	window_set_history(active_win, data);
+	GHashTable *optlist;
+        char *name;
+	void *free_arg;
+
+	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS,
+			    "window history", &optlist, &name))
+		return;
+
+	if (g_hash_table_lookup(optlist, "clear") != NULL) {
+		signal_continue(1, data);
+		window_clear_history(active_win, name);
+	} else {
+		window_set_history(active_win, name);
+	}
+
+	cmd_params_free(free_arg);
 }
 
 /* we're moving the first window to last - move the first contiguous block
@@ -883,6 +899,7 @@ void window_commands_init(void)
 	command_set_options("window number", "sticky");
 	command_set_options("window server", "sticky unsticky");
 	command_set_options("window theme", "delete");
+	command_set_options("window history", "clear");
 }
 
 void window_commands_deinit(void)

From ad842ea8a60f107d68df4298a8914e66edf95c3b Mon Sep 17 00:00:00 2001
From: ailin-nemui 
Date: Fri, 8 Jan 2016 15:42:59 +0100
Subject: [PATCH 0253/1650] reorder history add and fixes

---
 src/fe-common/core/command-history.c | 10 ----------
 src/fe-common/core/window-commands.c |  4 ++--
 src/fe-text/gui-readline.c           | 15 +++++++--------
 3 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/src/fe-common/core/command-history.c b/src/fe-common/core/command-history.c
index 9f46ee99..1060744e 100644
--- a/src/fe-common/core/command-history.c
+++ b/src/fe-common/core/command-history.c
@@ -33,7 +33,6 @@
 static HISTORY_REC *global_history;
 static int window_history;
 static GSList *histories;
-static HISTORY_REC *last_cleared_history;
 
 void command_history_add(HISTORY_REC *history, const char *text)
 {
@@ -42,13 +41,6 @@ void command_history_add(HISTORY_REC *history, const char *text)
 	g_return_if_fail(history != NULL);
 	g_return_if_fail(text != NULL);
 
-	if (last_cleared_history == history) {
-		last_cleared_history = NULL;
-		return; /* ignore this history addition, we just
-			   cleared it */
-	}
-	last_cleared_history = NULL;
-
 	link = g_list_last(history->list);
 	if (link != NULL && g_strcmp0(link->data, text) == 0)
 	  return; /* same as previous entry */
@@ -195,7 +187,6 @@ void command_history_clear(HISTORY_REC *history)
 	g_list_free(history->list);
 	history->list = NULL;
 	history->lines = 0;
-	last_cleared_history = history;
 }
 
 void command_history_destroy(HISTORY_REC *history)
@@ -207,7 +198,6 @@ void command_history_destroy(HISTORY_REC *history)
 
 	histories = g_slist_remove(histories, history);
 	command_history_clear(history);
-	last_cleared_history = NULL; /* was destroyed */
 
 	g_free_not_null(history->name);
 	g_free(history);
diff --git a/src/fe-common/core/window-commands.c b/src/fe-common/core/window-commands.c
index e5005144..9e4aab3a 100644
--- a/src/fe-common/core/window-commands.c
+++ b/src/fe-common/core/window-commands.c
@@ -620,10 +620,10 @@ static void cmd_window_name(const char *data)
 void cmd_window_history(const char *data)
 {
 	GHashTable *optlist;
-        char *name;
+	char *name;
 	void *free_arg;
 
-	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS,
+	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_STRIP_TRAILING_WS,
 			    "window history", &optlist, &name))
 		return;
 
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index fcf152e8..5acfaf60 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -456,22 +456,21 @@ static void key_send_line(void)
 	add_history = *str != '\0';
 	history = command_history_current(active_win);
 
+	if (redir != NULL && redir->flags & ENTRY_REDIRECT_FLAG_HIDDEN)
+		add_history = 0;
+
+	if (add_history && history != NULL) {
+		command_history_add(history, str);
+	}
+
 	if (redir == NULL) {
 		signal_emit("send command", 3, str,
 			    active_win->active_server,
 			    active_win->active);
 	} else {
-		if (redir->flags & ENTRY_REDIRECT_FLAG_HIDDEN)
-                        add_history = 0;
 		handle_entry_redirect(str);
 	}
 
-	if (add_history) {
-		history = command_history_find(history);
-		if (history != NULL)
-			command_history_add(history, str);
-	}
-
 	if (active_entry != NULL)
 		gui_entry_set_text(active_entry, "");
 	command_history_clear_pos(active_win);

From cf90b2122efdc2a6fc5246e3c538af3c71f38988 Mon Sep 17 00:00:00 2001
From: Lukas Mai 
Date: Fri, 8 Jan 2016 18:52:59 +0100
Subject: [PATCH 0254/1650] irc/core/irc-commands.c: fix indentation

---
 src/irc/core/irc-commands.c | 200 ++++++++++++++++++------------------
 1 file changed, 100 insertions(+), 100 deletions(-)

diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c
index 3cc105ba..d5988f97 100644
--- a/src/irc/core/irc-commands.c
+++ b/src/irc/core/irc-commands.c
@@ -61,16 +61,16 @@ static int knockout_tag;
 
 /* SYNTAX: NOTICE   */
 static void cmd_notice(const char *data, IRC_SERVER_REC *server,
-		       WI_ITEM_REC *item)
+                       WI_ITEM_REC *item)
 {
 	const char *target, *msg;
 	char *recoded;
 	void *free_arg;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST,
-			    &target, &msg))
+	                    &target, &msg))
 		return;
 	if (g_strcmp0(target, "*") == 0)
 		target = item == NULL ? NULL : window_item_get_target(item);
@@ -88,16 +88,16 @@ static void cmd_notice(const char *data, IRC_SERVER_REC *server,
 
 /* SYNTAX: CTCP   [] */
 static void cmd_ctcp(const char *data, IRC_SERVER_REC *server,
-		     WI_ITEM_REC *item)
+                     WI_ITEM_REC *item)
 {
 	const char *target;
 	char *ctcpcmd, *ctcpdata;
 	void *free_arg;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST,
-			    &target, &ctcpcmd, &ctcpdata))
+	                    &target, &ctcpcmd, &ctcpdata))
 		return;
 	if (g_strcmp0(target, "*") == 0)
 		target = item == NULL ? NULL : window_item_get_target(item);
@@ -122,16 +122,16 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server,
 
 /* SYNTAX: NCTCP   [] */
 static void cmd_nctcp(const char *data, IRC_SERVER_REC *server,
-		      WI_ITEM_REC *item)
+                      WI_ITEM_REC *item)
 {
 	const char *target;
 	char *ctcpcmd, *ctcpdata, *recoded;
 	void *free_arg;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST,
-			    &target, &ctcpcmd, &ctcpdata))
+	                    &target, &ctcpcmd, &ctcpdata))
 		return;
 	if (g_strcmp0(target, "*") == 0)
 		target = item == NULL ? NULL : window_item_get_target(item);
@@ -150,22 +150,22 @@ static void cmd_nctcp(const char *data, IRC_SERVER_REC *server,
 
 /* SYNTAX: PART [] [] */
 static void cmd_part(const char *data, IRC_SERVER_REC *server,
-		     WI_ITEM_REC *item)
+                     WI_ITEM_REC *item)
 {
 	char *channame, *msg;
 	char *recoded = NULL;
 	void *free_arg;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST |
-			    PARAM_FLAG_OPTCHAN, item, &channame, &msg))
+	                    PARAM_FLAG_OPTCHAN, item, &channame, &msg))
 		return;
 	if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
 
 	if (*msg == '\0') msg = (char *) settings_get_str("part_message");
 
-        if (server->cmdcount > MAX_COMMANDS_ON_PART_UNTIL_PURGE)
+	if (server->cmdcount > MAX_COMMANDS_ON_PART_UNTIL_PURGE)
 		irc_server_purge_output(server, channame);
 
 	if (*msg != '\0')
@@ -186,11 +186,11 @@ static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
 	char *channame, *nicks, *reason, *recoded;
 	void *free_arg;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST |
-			    PARAM_FLAG_OPTCHAN, item,
-			    &channame, &nicks, &reason))
+	                    PARAM_FLAG_OPTCHAN, item,
+	                    &channame, &nicks, &reason))
 		return;
 
 	if (*channame == '\0' || *nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
@@ -213,11 +213,11 @@ static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *ite
 	char *recoded = NULL;
 	void *free_arg;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN |
-			    PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
-			    item, "topic", &optlist, &channame, &topic))
+	                    PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST,
+	                    item, "topic", &optlist, &channame, &topic))
 		return;
 
 	if (*topic != '\0' || g_hash_table_lookup(optlist, "delete") != NULL)
@@ -239,7 +239,7 @@ static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *it
 	char *nick, *channame;
 	void *free_arg;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 2, &nick, &channame))
 		return;
@@ -258,17 +258,17 @@ static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *it
 
 /* SYNTAX: LIST [-yes] [] */
 static void cmd_list(const char *data, IRC_SERVER_REC *server,
-		     WI_ITEM_REC *item)
+                     WI_ITEM_REC *item)
 {
 	GHashTable *optlist;
 	char *str;
 	void *free_arg;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
-			    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, 
-			    "list", &optlist, &str))
+	                    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, 
+	                    "list", &optlist, &str))
 		return;
 
 	if (*str == '\0' && g_hash_table_lookup(optlist, "yes") == NULL &&
@@ -282,7 +282,7 @@ static void cmd_list(const char *data, IRC_SERVER_REC *server,
 
 /* SYNTAX: WHO [ |  | **] */
 static void cmd_who(const char *data, IRC_SERVER_REC *server,
-		    WI_ITEM_REC *item)
+                    WI_ITEM_REC *item)
 {
 	char *channel, *rest;
 	void *free_arg;
@@ -290,7 +290,7 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server,
 	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | 
-			    PARAM_FLAG_STRIP_TRAILING_WS, &channel, &rest))
+	                    PARAM_FLAG_STRIP_TRAILING_WS, &channel, &rest))
 		return;
 
 	if (g_strcmp0(channel, "*") == 0 || *channel == '\0') {
@@ -313,29 +313,29 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server,
 }
 
 static void cmd_names(const char *data, IRC_SERVER_REC *server,
-		      WI_ITEM_REC *item)
+                      WI_ITEM_REC *item)
 {
-        GHashTable *optlist;
+	GHashTable *optlist;
 	char *channel;
 	void *free_arg;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
-			    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
-			    "names", &optlist, &channel))
+	                    PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
+	                    "names", &optlist, &channel))
 		return;
 
 	if (g_strcmp0(channel, "*") == 0 || *channel == '\0') {
 		if (!IS_IRC_CHANNEL(item))
-                        cmd_param_error(CMDERR_NOT_JOINED);
+			cmd_param_error(CMDERR_NOT_JOINED);
 
 		channel = IRC_CHANNEL(item)->name;
 	}
 
 	if (g_strcmp0(channel, "**") == 0) {
 		/* ** displays all nicks.. */
-                irc_send_cmd(server, "NAMES");
+		irc_send_cmd(server, "NAMES");
 	} else {
 		irc_send_cmdv(server, "NAMES %s", channel);
 	}
@@ -346,12 +346,12 @@ static void cmd_names(const char *data, IRC_SERVER_REC *server,
 /* SYNTAX: NICK  */
 static void cmd_nick(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
 {
-        char *nick;
+	char *nick;
 	void *free_arg;
 
 	g_return_if_fail(data != NULL);
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 1, &nick))
 		return;
@@ -388,23 +388,23 @@ static char *get_redirect_nicklist(const char *nicks, int *free)
 
 /* SYNTAX: WHOIS [-] [] [] */
 static void cmd_whois(const char *data, IRC_SERVER_REC *server,
-		      WI_ITEM_REC *item)
+                      WI_ITEM_REC *item)
 {
 	GHashTable *optlist;
 	char *qserver, *query, *event_402, *str;
 	void *free_arg;
 	int free_nick;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS |
-			    PARAM_FLAG_UNKNOWN_OPTIONS,
-			    "whois", &optlist, &qserver, &query))
+	                    PARAM_FLAG_UNKNOWN_OPTIONS,
+	                    "whois", &optlist, &qserver, &query))
 		return;
 
 	/* - */
 	server = IRC_SERVER(cmd_options_get_server("whois", optlist,
-						   SERVER(server)));
+	                                           SERVER(server)));
 	if (server == NULL) {
 		cmd_params_free(free_arg);
 		return;
@@ -439,15 +439,15 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server,
 
 	str = g_strconcat(qserver, " ", query, NULL);
 	server_redirect_event(server, "whois", 1, str, TRUE,
-		      NULL,
-		      "event 318", "whois end",
-		      "event 402", event_402,
-		      "event 301", "whois away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
-		      "event 313", "whois oper",
-		      "event 401", (settings_get_bool("auto_whowas") ? "whois try whowas" : "whois event not found"),
-		      "event 311", "whois event",
-		      "", "whois default event", NULL);
-        g_free(str);
+	              NULL,
+	              "event 318", "whois end",
+	              "event 402", event_402,
+	              "event 301", "whois away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
+	              "event 313", "whois oper",
+	              "event 401", (settings_get_bool("auto_whowas") ? "whois try whowas" : "whois event not found"),
+	              "event 311", "whois event",
+	              "", "whois default event", NULL);
+	g_free(str);
 
 	server->whois_found = FALSE;
 	irc_send_cmd_split(server, tmpstr->str, 2, server->max_whois_in_cmd);
@@ -457,7 +457,7 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server,
 }
 
 static void event_whois(IRC_SERVER_REC *server, const char *data,
-			const char *nick, const char *addr)
+                        const char *nick, const char *addr)
 {
 	server->whois_found = TRUE;
 	signal_emit("event 311", 4, server, data, nick, addr);
@@ -473,23 +473,23 @@ static void sig_whois_try_whowas(IRC_SERVER_REC *server, const char *data)
 
 	server->whowas_found = FALSE;
 	server_redirect_event(server, "whowas", 1, nick, -1, NULL,
-			      "event 314", "whowas event",
-			      "event 369", "whowas event end",
-			      "event 406", "event empty", NULL);
+	                      "event 314", "whowas event",
+	                      "event 369", "whowas event end",
+	                      "event 406", "event empty", NULL);
 	irc_send_cmdv(server, "WHOWAS %s 1", nick);
 
 	g_free(params);
 }
 
 static void event_end_of_whois(IRC_SERVER_REC *server, const char *data,
-			       const char *nick, const char *addr)
+                               const char *nick, const char *addr)
 {
 	signal_emit("event 318", 4, server, data, nick, addr);
 	server->whois_found = FALSE;
 }
 
 static void event_whowas(IRC_SERVER_REC *server, const char *data,
-			 const char *nick, const char *addr)
+                         const char *nick, const char *addr)
 {
 	server->whowas_found = TRUE;
 	signal_emit("event 314", 4, server, data, nick, addr);
@@ -502,17 +502,17 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
 	void *free_arg;
 	int free_nick;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS,
-			    &nicks, &rest))
+	                    &nicks, &rest))
 		return;
 	if (*nicks == '\0') nicks = server->nick;
 
 	nicks_redir = get_redirect_nicklist(nicks, &free_nick);
 	server_redirect_event(server, "whowas", 1, nicks_redir, -1, NULL,
-			      "event 301", "whowas away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
-			      "event 314", "whowas event", NULL);
+	                      "event 301", "whowas away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
+	                      "event 314", "whowas event", NULL);
 	if (free_nick) g_free(nicks_redir);
 
 	server->whowas_found = FALSE;
@@ -529,9 +529,9 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
 static void cmd_ping(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
 {
 	GTimeVal tv;
-        char *str;
+	char *str;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (*data == '\0') {
 		if (!IS_QUERY(item))
@@ -554,7 +554,7 @@ static void cmd_away(const char *data, IRC_SERVER_REC *server)
 	void *free_arg;
 
 	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
-			    PARAM_FLAG_GETREST, "away", &optlist, &reason)) return;
+	                    PARAM_FLAG_GETREST, "away", &optlist, &reason)) return;
 
 	if (g_hash_table_lookup(optlist, "one") != NULL)
 		irc_server_send_away(server, reason);
@@ -567,7 +567,7 @@ static void cmd_away(const char *data, IRC_SERVER_REC *server)
 /* SYNTAX: SCONNECT  [[] ] */
 static void cmd_sconnect(const char *data, IRC_SERVER_REC *server)
 {
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 	if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
 
 	irc_send_cmdv(server, "CONNECT %s", data);
@@ -600,11 +600,11 @@ static void cmd_wait(const char *data, IRC_SERVER_REC *server)
 	void *free_arg;
 	int n;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
-			    PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
-			    NULL, &optlist, &msecs))
+	                    PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
+	                    NULL, &optlist, &msecs))
 		return;
 
 	if (*msecs == '\0')
@@ -612,7 +612,7 @@ static void cmd_wait(const char *data, IRC_SERVER_REC *server)
 
 	/* - */
 	server = IRC_SERVER(cmd_options_get_server(NULL, optlist,
-						   SERVER(server)));
+	                                           SERVER(server)));
 
 	n = atoi(msecs);
 	if (server != NULL && n > 0) {
@@ -635,10 +635,10 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
 	IRC_CHANNEL_REC *chanrec;
 	GSList *tmp, *nicks;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN |
-			    PARAM_FLAG_GETREST, item, &channame, &msg))
+	                    PARAM_FLAG_GETREST, item, &channame, &msg))
 		return;
 	if (*msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
 
@@ -654,11 +654,11 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
 		/* Fall back to manually noticing each op */
 		nicks = NULL;
 		g_hash_table_foreach(chanrec->nicks,
-				     (GHFunc) cmd_wall_hash, &nicks);
+		                     (GHFunc) cmd_wall_hash, &nicks);
 
 		args = g_strconcat(chanrec->name, " ", recoded, NULL);
 		msg = parse_special_string(settings_get_str("wall_format"),
-					   SERVER(server), item, args, NULL, 0);
+		                           SERVER(server), item, args, NULL, 0);
 		g_free(args);
 
 		for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
@@ -666,7 +666,7 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
 
 			if (rec != chanrec->ownnick) {
 				irc_send_cmdv(server, "NOTICE %s :%s",
-					      rec->nick, msg);
+				              rec->nick, msg);
 			}
 		}
 
@@ -680,17 +680,17 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
 
 /* SYNTAX: KICKBAN []   */
 static void cmd_kickban(const char *data, IRC_SERVER_REC *server,
-			WI_ITEM_REC *item)
+                        WI_ITEM_REC *item)
 {
-        IRC_CHANNEL_REC *chanrec;
+	IRC_CHANNEL_REC *chanrec;
 	char *channel, *nicks, *reason, *kickcmd, *bancmd, *recoded;
-        char **nicklist, *spacenicks;
+	char **nicklist, *spacenicks;
 	void *free_arg;
 
-        CMD_IRC_SERVER(server);
+	CMD_IRC_SERVER(server);
 
 	if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST,
-			    item, &channel, &nicks, &reason))
+	                    item, &channel, &nicks, &reason))
 		return;
 
 	if (*channel == '\0' || *nicks == '\0')
@@ -701,7 +701,7 @@ static void cmd_kickban(const char *data, IRC_SERVER_REC *server,
 		cmd_param_error(CMDERR_CHAN_NOT_FOUND);
 
 	nicklist = g_strsplit(nicks, ",", -1);
-        spacenicks = g_strjoinv(" ", nicklist);
+	spacenicks = g_strjoinv(" ", nicklist);
 	g_strfreev(nicklist);
 
 	recoded = recode_out(SERVER(server), reason, channel);
@@ -709,9 +709,9 @@ static void cmd_kickban(const char *data, IRC_SERVER_REC *server,
 	g_free(recoded);
 
 	bancmd = g_strdup_printf("%s %s", chanrec->name, spacenicks);
-        g_free(spacenicks);
+	g_free(spacenicks);
 
-        if (settings_get_bool("kick_first_on_kickban")) {
+	if (settings_get_bool("kick_first_on_kickban")) {
 		signal_emit("command kick", 3, kickcmd, server, chanrec);
 		signal_emit("command ban", 3, bancmd, server, chanrec);
 	} else {
@@ -742,7 +742,7 @@ static void knockout_timeout_server(IRC_SERVER_REC *server)
 	if (!IS_IRC_SERVER(server))
 		return;
 
-        now = time(NULL);
+	now = time(NULL);
 	for (tmp = server->knockoutlist; tmp != NULL; tmp = next) {
 		KNOCKOUT_REC *rec = tmp->data;
 
@@ -763,16 +763,16 @@ static int knockout_timeout(void)
 
 /* SYNTAX: KNOCKOUT [