summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.travis.yml43
-rw-r--r--INSTALL7
-rw-r--r--Makefile.am3
-rw-r--r--NEWS12
-rw-r--r--acconfig.h3
-rwxr-xr-xautogen.sh8
-rw-r--r--configure.ac73
-rw-r--r--default.theme2
-rw-r--r--docs/Makefile.am2
-rw-r--r--docs/help/in/connect.in2
-rw-r--r--docs/help/in/dcc.in4
-rw-r--r--docs/help/in/disconnect.in7
-rw-r--r--docs/help/in/echo.in4
-rw-r--r--docs/help/in/irssiproxy.in14
-rw-r--r--docs/help/in/lastlog.in16
-rw-r--r--docs/help/in/list.in15
-rw-r--r--docs/help/in/msg.in4
-rw-r--r--docs/help/in/network.in6
-rw-r--r--docs/help/in/server.in3
-rw-r--r--docs/help/in/window.in84
-rw-r--r--docs/irssi.164
-rw-r--r--docs/perl.txt12
-rw-r--r--docs/proxy.txt22
-rw-r--r--docs/signals.txt10
-rw-r--r--docs/startup-HOWTO.html4
-rwxr-xr-xirssi-version.sh19
-rw-r--r--m4/curses.m42
-rw-r--r--m4/glib-2.0.m42
-rw-r--r--scripts/Makefile.am2
-rw-r--r--scripts/autoop.pl73
-rw-r--r--scripts/autorejoin.pl71
-rw-r--r--scripts/buf.pl17
-rw-r--r--scripts/dns.pl22
-rw-r--r--scripts/kills.pl9
-rw-r--r--scripts/mail.pl4
-rw-r--r--scripts/mlock.pl2
-rw-r--r--scripts/quitmsg.pl4
-rw-r--r--scripts/sb_search.pl142
-rw-r--r--scripts/scriptassist.pl2
-rw-r--r--scripts/splitlong.pl60
-rw-r--r--scripts/usercount.pl3
-rw-r--r--src/common.h13
-rw-r--r--src/core/channels-setup.c17
-rw-r--r--src/core/channels-setup.h3
-rw-r--r--src/core/channels.c2
-rw-r--r--src/core/chat-commands.c16
-rw-r--r--src/core/chatnets.c2
-rw-r--r--src/core/commands.c7
-rw-r--r--src/core/commands.h4
-rw-r--r--src/core/core.c8
-rw-r--r--src/core/ignore.c21
-rw-r--r--src/core/levels.c4
-rw-r--r--src/core/log-away.c7
-rw-r--r--src/core/log.c16
-rw-r--r--src/core/misc.c65
-rw-r--r--src/core/misc.h5
-rw-r--r--src/core/modules-load.c18
-rw-r--r--src/core/modules.c4
-rw-r--r--src/core/net-nonblock.h2
-rw-r--r--src/core/net-sendbuffer.c2
-rw-r--r--src/core/net-sendbuffer.h2
-rw-r--r--src/core/network-openssl.c9
-rw-r--r--src/core/network.c2
-rw-r--r--src/core/nicklist.c12
-rw-r--r--src/core/nicklist.h1
-rw-r--r--src/core/query-rec.h2
-rw-r--r--src/core/rawlog.c12
-rw-r--r--src/core/recode.c20
-rw-r--r--src/core/recode.h2
-rw-r--r--src/core/server-connect-rec.h1
-rw-r--r--src/core/server-setup-rec.h4
-rw-r--r--src/core/servers-reconnect.c10
-rw-r--r--src/core/servers-setup.c27
-rw-r--r--src/core/servers-setup.h3
-rw-r--r--src/core/servers.c1
-rw-r--r--src/core/servers.h2
-rw-r--r--src/core/session.c15
-rw-r--r--src/core/settings.c35
-rw-r--r--src/core/settings.h5
-rw-r--r--src/fe-common/core/command-history.c6
-rw-r--r--src/fe-common/core/completion.c15
-rw-r--r--src/fe-common/core/fe-channels.c9
-rw-r--r--src/fe-common/core/fe-common-core.c18
-rw-r--r--src/fe-common/core/fe-exec.c2
-rw-r--r--src/fe-common/core/fe-help.c6
-rw-r--r--src/fe-common/core/fe-ignore.c5
-rw-r--r--src/fe-common/core/fe-log.c17
-rw-r--r--src/fe-common/core/fe-messages.c30
-rw-r--r--src/fe-common/core/fe-queries.c7
-rw-r--r--src/fe-common/core/fe-recode.c2
-rw-r--r--src/fe-common/core/fe-server.c10
-rw-r--r--src/fe-common/core/fe-settings.c38
-rw-r--r--src/fe-common/core/formats.c7
-rw-r--r--src/fe-common/core/hilight-text.c26
-rw-r--r--src/fe-common/core/keyboard.c61
-rw-r--r--src/fe-common/core/module-formats.c4
-rw-r--r--src/fe-common/core/themes.c10
-rw-r--r--src/fe-common/core/window-commands.c4
-rw-r--r--src/fe-common/core/windows-layout.c9
-rw-r--r--src/fe-common/irc/Makefile.am1
-rw-r--r--src/fe-common/irc/dcc/fe-dcc-chat.c4
-rw-r--r--src/fe-common/irc/dcc/fe-dcc-get.c5
-rw-r--r--src/fe-common/irc/fe-common-irc.c9
-rw-r--r--src/fe-common/irc/fe-ctcp.c8
-rw-r--r--src/fe-common/irc/fe-events-numeric.c8
-rw-r--r--src/fe-common/irc/fe-events.c17
-rw-r--r--src/fe-common/irc/fe-irc-channels.c47
-rw-r--r--src/fe-common/irc/fe-irc-channels.h10
-rw-r--r--src/fe-common/irc/fe-irc-commands.c12
-rw-r--r--src/fe-common/irc/fe-irc-messages.c108
-rw-r--r--src/fe-common/irc/fe-irc-queries.c2
-rw-r--r--src/fe-common/irc/fe-irc-server.c3
-rw-r--r--src/fe-common/irc/fe-ircnet.c35
-rw-r--r--src/fe-common/irc/fe-modes.c4
-rw-r--r--src/fe-common/irc/fe-netjoin.c2
-rw-r--r--src/fe-common/irc/fe-sasl.c48
-rw-r--r--src/fe-common/irc/fe-whois.c10
-rw-r--r--src/fe-common/irc/module-formats.c2
-rw-r--r--src/fe-common/irc/module-formats.h2
-rw-r--r--src/fe-text/gui-entry.c6
-rw-r--r--src/fe-text/gui-printtext.c7
-rw-r--r--src/fe-text/gui-readline.c25
-rw-r--r--src/fe-text/irssi.c26
-rw-r--r--src/fe-text/lastlog.c31
-rw-r--r--src/fe-text/mainwindows-layout.c3
-rw-r--r--src/fe-text/module-formats.c1
-rw-r--r--src/fe-text/module-formats.h1
-rw-r--r--src/fe-text/statusbar-config.c24
-rw-r--r--src/fe-text/statusbar-items.c10
-rw-r--r--src/fe-text/statusbar.c4
-rw-r--r--src/fe-text/term-terminfo.c35
-rw-r--r--src/fe-text/term.h2
-rw-r--r--src/fe-text/terminfo-core.c120
-rw-r--r--src/fe-text/terminfo-core.h4
-rw-r--r--src/fe-text/tparm.c12
-rw-r--r--src/irc/core/Makefile.am4
-rw-r--r--src/irc/core/bans.c20
-rw-r--r--src/irc/core/channel-events.c2
-rw-r--r--src/irc/core/channel-rejoin.c2
-rw-r--r--src/irc/core/channels-query.c2
-rw-r--r--src/irc/core/irc-cap.c192
-rw-r--r--src/irc/core/irc-cap.h9
-rw-r--r--src/irc/core/irc-channels.c33
-rw-r--r--src/irc/core/irc-chatnets.c26
-rw-r--r--src/irc/core/irc-chatnets.h9
-rw-r--r--src/irc/core/irc-commands.c74
-rw-r--r--src/irc/core/irc-core.c8
-rw-r--r--src/irc/core/irc-expandos.c38
-rw-r--r--src/irc/core/irc-nicklist.c26
-rw-r--r--src/irc/core/irc-nicklist.h3
-rw-r--r--src/irc/core/irc-queries.c10
-rw-r--r--src/irc/core/irc-servers-reconnect.c3
-rw-r--r--src/irc/core/irc-servers-setup.c36
-rw-r--r--src/irc/core/irc-servers.c98
-rw-r--r--src/irc/core/irc-servers.h11
-rw-r--r--src/irc/core/irc-session.c19
-rw-r--r--src/irc/core/irc.c8
-rw-r--r--src/irc/core/irc.h6
-rw-r--r--src/irc/core/modes.c14
-rw-r--r--src/irc/core/sasl.c178
-rw-r--r--src/irc/core/sasl.h34
-rw-r--r--src/irc/core/servers-redirect.c18
-rw-r--r--src/irc/dcc/dcc-autoget.c4
-rw-r--r--src/irc/dcc/dcc-chat.c4
-rw-r--r--src/irc/dcc/dcc-get.c5
-rw-r--r--src/irc/dcc/dcc-send.c4
-rw-r--r--src/irc/dcc/dcc.c8
-rw-r--r--src/irc/flood/flood.c4
-rw-r--r--src/irc/notifylist/notify-commands.c3
-rw-r--r--src/irc/notifylist/notify-setup.c6
-rw-r--r--src/irc/notifylist/notifylist.c2
-rw-r--r--src/irc/proxy/dump.c40
-rw-r--r--src/irc/proxy/listen.c116
-rw-r--r--src/irc/proxy/proxy.c58
-rw-r--r--src/irc/proxy/proxy.h1
-rw-r--r--src/lib-config/get.c62
-rw-r--r--src/lib-config/iconfig.h4
-rw-r--r--src/lib-config/parse.c4
-rw-r--r--src/lib-config/set.c8
-rw-r--r--src/perl/common/Core.xs2
-rw-r--r--src/perl/common/Irssi.pm2
-rw-r--r--src/perl/irc/Irc.xs130
-rw-r--r--src/perl/irssi-core.pl4
-rw-r--r--src/perl/perl-common.c230
-rw-r--r--src/perl/perl-core.c6
-rw-r--r--src/perl/perl-fe.c2
-rw-r--r--src/perl/perl-signals.c40
-rw-r--r--src/perl/textui/Statusbar.xs4
-rw-r--r--src/perl/textui/TextUI.xs66
-rw-r--r--src/perl/ui/UI.xs64
-rwxr-xr-xsyntax.pl2
192 files changed, 2504 insertions, 1438 deletions
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]*
diff --git a/.travis.yml b/.travis.yml
index 04c19d88..46f58766 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,27 +1,26 @@
-language: c
-compiler:
- - gcc
- - clang
+sudo: false
+language: perl
+perl:
+ - "5.20-shrplib"
+ - "5.18-shrplib"
+ - "system-perl"
+env:
+ - CC=clang
+ - CC=gcc
+
+addons:
+ apt:
+ packages:
+ - libperl-dev
+ - elinks
before_install:
- - sudo apt-get update -qq
- - sudo apt-get build-dep -qq irssi
- - sudo apt-get install -qq lynx
+ - perl -V
+
+install: true
script:
- - ./autogen.sh --with-proxy --with-bot
+ - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build
- cat config.log
- - make
- - sudo 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
+ - make CFLAGS="-Wall -Werror"
+ - make install
diff --git a/INSTALL b/INSTALL
index 719369de..234c6cf6 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,7 +11,8 @@ To compile irssi you need:
For most people, this should work just fine:
- ./configure
+ ./autogen.sh (for people who just cloned the repository)
+ ./configure (if this script already exists, skip ./autogen.sh)
make
su
make install (not _really_ required except for perl support)
@@ -94,6 +95,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:
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/NEWS b/NEWS
index de36d195..511f495a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,9 @@
v0.8.18-head 2014-XX-YY The Irssi team <staff@irssi.org>
+ + 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.
v0.8.17 2014-10-11 The Irssi team <staff@irssi.org>
+ Document that SSL connections aren't properly handled during /UPGRADE. See Github PR #39.
@@ -368,7 +372,7 @@ v0.8.10 2005-12-11 The Irssi team <staff@irssi.org>
<charset> 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 +1909,7 @@ v0.7.14 1999-08-22 Timo Sirainen <cras@irccrew.org> [unstable]
- /msg <tab> 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 +2193,7 @@ v0.7.9 1999-04-22 Timo Sirainen <a@sicom.fi> [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 +2639,7 @@ v0.3.2 1999-01-22 Timo Sirainen <a@sicom.fi> [unstable]
v0.3.1 1999-01-22 Timo Sirainen <a@sicom.fi>
- * 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/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/autogen.sh b/autogen.sh
index cf4b9798..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
@@ -28,9 +32,11 @@ 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
+ 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
diff --git a/configure.ac b/configure.ac
index 477f8c4d..325b5e5d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,9 +7,10 @@ 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_ISC_POSIX
AC_PROG_CC
AC_PROG_CPP
AM_PROG_LIBTOOL
@@ -20,7 +21,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
@@ -84,15 +85,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],
@@ -197,38 +189,22 @@ 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
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 <sys/types.h>
-#include <sys/socket.h>],
-[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 <sys/socket.h> 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 <sys/socket.h> doesn't define.])], [
+AC_INCLUDES_DEFAULT
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+])
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
@@ -287,7 +263,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)
@@ -340,28 +316,6 @@ if test "$enable_ssl" = "yes"; then
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 **
@@ -799,7 +753,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/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.
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
diff --git a/docs/help/in/connect.in b/docs/help/in/connect.in
index 1c1aa2bb..df50d1b9 100644
--- a/docs/help/in/connect.in
+++ b/docs/help/in/connect.in
@@ -11,9 +11,11 @@
-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.
+ -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/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
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/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/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/lastlog.in b/docs/help/in/lastlog.in
index e7b90d42..e96e2ed5 100644
--- a/docs/help/in/lastlog.in
+++ b/docs/help/in/lastlog.in
@@ -10,15 +10,19 @@
-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.
+ -<level>: 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.
+ -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.
- -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.
+ <count>: Display a maximum number of `count' lines.
+ <start>: 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,8 +34,10 @@
%9Examples:%9
/LASTLOG holiday
- /LASTLOG 'is on vacation'
- /LASTLOG -file -force ~/mike.log 'mike'
+ /LASTLOG 'is on vacation' 10
+ /LASTLOG -force -file ~/mike.log 'mike'
+ /LASTLOG -hilight
+ /LASTLOG -5 searchterm
%9See also:%9 HILIGHT, SCROLLBACK
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
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/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/docs/help/in/server.in b/docs/help/in/server.in
index d8bcb9a7..e407b6a9 100644
--- a/docs/help/in/server.in
+++ b/docs/help/in/server.in
@@ -18,10 +18,11 @@
-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.
+ -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/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/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 <cras@irssi.org>
-.sp
-This manpage was written by Istvan Sebestyen
-.BR <stevee@alphanet.ch>
-and Stefan Tomanek
-.BR <stefan@pico.ruhr.de>
+was written by Timo Sirainen; this manpage was written by Istvan Sebestyen, Stefan Tomanek, Geert Hauwaerts.
diff --git a/docs/perl.txt b/docs/perl.txt
index 732b73af..560fcaec 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->{}
@@ -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
diff --git a/docs/proxy.txt b/docs/proxy.txt
index 41875aab..e6360a82 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:
+
+ /IRSSIPROXY status
diff --git a/docs/signals.txt b/docs/signals.txt
index f0860d3e..8b71fd95 100644
--- a/docs/signals.txt
+++ b/docs/signals.txt
@@ -131,6 +131,15 @@ irc-nicklist.c:
irc-servers.c:
"event connected", SERVER_REC
+irc-cap.c
+ "server cap ack "<cmd>, SERVER_REC
+ "server cap nak "<cmd>, 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
@@ -220,6 +229,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
diff --git a/docs/startup-HOWTO.html b/docs/startup-HOWTO.html
index 736f25e9..deff3116 100644
--- a/docs/startup-HOWTO.html
+++ b/docs/startup-HOWTO.html
@@ -391,7 +391,7 @@ messages window.</p>
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:</p>
<pre>
@@ -493,7 +493,7 @@ scrollback buffer. Simplest usages are</p>
<pre>
/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
</pre>
diff --git a/irssi-version.sh b/irssi-version.sh
index 49abc55e..1fc6a558 100755
--- a/irssi-version.sh
+++ b/irssi-version.sh
@@ -5,5 +5,24 @@ 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"
+
+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 "#undef PACKAGE_VERSION"
+ echo "#define PACKAGE_VERSION \"${version}\""
+ fi
+fi
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
)
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/scripts/Makefile.am b/scripts/Makefile.am
index b3c641b7..cd795153 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -11,9 +11,7 @@ script_DATA = \
mail.pl \
mlock.pl \
quitmsg.pl \
- sb_search.pl \
scriptassist.pl \
- splitlong.pl \
usercount.pl
EXTRA_DIST = $(script_DATA)
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 = <CONF>) {
+ 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;
+
+my @tags;
+my $acttag = 0;
+
+sub rejoin {
+ my ( $data ) = @_;
+ my ( $tag, $servtag, $channel, $pass ) = split( / +/, $data );
- # 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 $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);
-
- 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;
- }
- }
+ my ( $server, $data ) = @_;
+ my ( $channel, $nick ) = split( / +/, $data );
+
+ return if ( $server->{ nick } ne $nick );
+
+ # 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/, <BUF>;
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 <nick>|<host>|<ip> ...
+# 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 <inch@stmpd.net>
-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 <nick>|<host>|<ip> ...',
- license => 'Public Domain',
- changed => 'Sun Mar 10 23:23 EET 2002'
+ authors => "Timo \'cras\' Sirainen",
+ contact => "tss\@iki.fi",
+ name => "dns",
+ description => "/DNS <nick>|<host>|<ip> ...",
+ 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(<f>) { $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 43fc7b55..00000000
--- a/scripts/sb_search.pl
+++ /dev/null
@@ -1,142 +0,0 @@
-# sb_search.pl - search in your scrollback, scroll to a match
-# Do /HELP SCROLLBACK for help
-
-# Copyright (C) 2008 Wouter Coekaerts <wouter@coekaerts.be>, Emanuele Giaquinta <exg@irssi.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 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.0';
-%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 ( <<SCRIPTHELP_EOF
-
-SCROLLBACK SEARCH [-level <level>] [-regexp] [-case] [-word] [-forward] [-all] [<pattern>]
-
- -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
- <pattern>: text to search for
-SCRIPTHELP_EOF
- ,MSGLEVEL_CLIENTCRAP);
- }
-}
-
-
-sub cmd_sb_search ($$$) {
- my ($args, $server, $witem) = @_;
-
- ### handle options
-
- my ($options, $pattern) = Irssi::command_parse_options('scrollback search', $args);
-
- my $level;
- 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/;
- } 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
-
- 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/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" }();
}
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');
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);
diff --git a/src/common.h b/src/common.h
index bb246962..86a079fe 100644
--- a/src/common.h
+++ b/src/common.h
@@ -43,19 +43,6 @@
# include <gmodule.h>
#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
-
-#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/core/channels-setup.c b/src/core/channels-setup.c
index e1289c23..2902ef8e 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);
@@ -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/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 235a9fc4..8e881679 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 -<chatnet> option is used to specify chat protocol */
@@ -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 <cert>] [-ssl_pkey <pkey>] [-ssl_pass <password>]
[-ssl_verify] [-ssl_cafile <cafile>] [-ssl_capath <capath>]
+ [-ssl_ciphers <list>]
[-!] [-noautosendcmd]
[-noproxy] [-network <network>] [-host <hostname>]
[-rawlog <file>]
@@ -244,6 +247,7 @@ static void sig_default_command_server(const char *data, SERVER_REC *server,
/* SYNTAX: SERVER [-4 | -6] [-ssl] [-ssl_cert <cert>] [-ssl_pkey <pkey>] [-ssl_pass <password>]
[-ssl_verify] [-ssl_cafile <cafile>] [-ssl_capath <capath>]
+ [-ssl_ciphers <list>]
[-!] [-noautosendcmd]
[-noproxy] [-network <network>] [-host <hostname>]
[-rawlog <file>]
@@ -283,7 +287,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);
@@ -321,7 +325,7 @@ static void cmd_quit(const char *data)
signal_emit("gui exit", 0);
}
-/* SYNTAX: MSG [-<server tag>] [-channel | -nick] <targets> <message> */
+/* SYNTAX: MSG [-<server tag>] [-channel | -nick] *|<targets> <message> */
static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
{
GHashTable *optlist;
@@ -343,7 +347,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 +359,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);
@@ -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/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/commands.c b/src/core/commands.c
index ed82f44e..88d1208c 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);
@@ -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 c68c5b24..72105ad3 100644
--- a/src/core/commands.h
+++ b/src/core/commands.h
@@ -152,13 +152,15 @@ 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);
/* 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/core.c b/src/core/core.c
index b9debbb5..bbeec6f4 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, NULL);
+
+ g_free(current_dir);
g_free(tmp_str);
}
+
return new_str;
}
diff --git a/src/core/ignore.c b/src/core/ignore.c
index 3c45967c..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 :
@@ -201,10 +200,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 +231,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)
@@ -263,7 +262,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 +280,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);
}
}
@@ -360,8 +359,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 +377,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)
@@ -438,7 +435,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/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-away.c b/src/core/log-away.c
index 681edcbf..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;
@@ -62,6 +63,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 +87,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);
diff --git a/src/core/log.c b/src/core/log.c
index d4d3853e..8306d2df 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;
}
@@ -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/misc.c b/src/core/misc.c
index 5e6087cb..490b5a8f 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;
}
@@ -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 == NULL)
+ 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)
{
@@ -269,7 +293,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;
}
@@ -967,19 +991,30 @@ char *ascii_strdown(char *str)
return str;
}
-char **strsplit_len(const char *str, int len)
-{
- char **ret;
- size_t total_len = strlen(str);
- int n = total_len / len;
- int i;
-
- 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);
+char **strsplit_len(const char *str, int len, gboolean onspace)
+{
+ char **ret = g_new(char *, 1);
+ int n;
+ int offset;
+
+ 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
+ * the space on the previous line.
+ */
+ int i;
+ for (i = len - 1; i > 0; i--) {
+ if (str[i] == ' ') {
+ offset = i;
+ break;
+ }
+ }
+ }
+ ret[n] = g_strndup(str, 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..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);
@@ -116,6 +119,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/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/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-openssl.c b/src/core/network-openssl.c
index e16403ec..465c4154 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,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);
+ 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;
@@ -531,6 +536,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);
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..770b0afc 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;
@@ -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;
}
@@ -571,6 +571,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) != NULL;
+}
+
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/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/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)
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/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..2c9614c7 100644
--- a/src/core/server-setup-rec.h
+++ b/src/core/server-setup-rec.h
@@ -8,11 +8,15 @@ char *address;
int port;
char *password;
+int sasl_mechanism;
+char *sasl_password;
+
char *ssl_cert;
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 0a08b461..f419035b 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;
}
@@ -253,6 +254,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);
@@ -381,7 +385,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) {
@@ -416,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);
diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index 0819ff1a..771e3999 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"));
@@ -176,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);
@@ -402,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)
@@ -427,7 +433,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);
@@ -442,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",
@@ -483,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);
}
@@ -497,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_if_fail(chatnet != 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);
@@ -523,7 +546,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/servers-setup.h b/src/core/servers-setup.h
index f7601a68..e7ff7abf 100644
--- a/src/core/servers-setup.h
+++ b/src/core/servers-setup.h
@@ -39,6 +39,9 @@ SERVER_SETUP_REC *server_setup_find(const char *address, int port,
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/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/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/core/session.c b/src/core/session.c
index b3002632..17d80076 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);
@@ -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);
@@ -187,7 +188,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 +224,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..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;
}
@@ -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);
@@ -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)
@@ -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);
@@ -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;
}
@@ -295,7 +296,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;
}
@@ -324,7 +325,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)
@@ -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 */
@@ -420,7 +421,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) {
@@ -428,7 +429,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 +459,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) {
@@ -468,7 +469,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 +503,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);
@@ -520,7 +521,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 +549,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/core/settings.h b/src/core/settings.h
index f8d9f68f..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 {
@@ -36,6 +37,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/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..a4715d23 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;
@@ -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;
@@ -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);
@@ -681,8 +680,8 @@ 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))
- *list = completion_get_settings(word, -1);
+ !g_strcmp0("-clear", line) || !g_strcmp0("-default", line))
+ *list = completion_get_settings(word, SETTING_TYPE_ANY);
else if (*line != '\0' && *word == '\0') {
SETTINGS_REC *rec = settings_get_record(line);
if (rec != NULL) {
@@ -758,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;
@@ -785,7 +784,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/fe-channels.c b/src/fe-common/core/fe-channels.c
index aefd1034..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;
@@ -287,7 +288,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 +524,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 +562,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-common-core.c b/src/fe-common/core/fe-common-core.c
index a475f056..a15850e2 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;
@@ -447,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);
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..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;
@@ -165,7 +166,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..f2c4c014 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);
@@ -485,7 +486,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,
@@ -616,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)
@@ -629,7 +630,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;
}
@@ -656,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);
}
diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c
index 97f3d84d..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);
@@ -242,13 +244,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 = (!g_strcmp0(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 +261,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);
}
@@ -314,8 +325,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 :
@@ -560,7 +571,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;
}
@@ -685,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);
diff --git a/src/fe-common/core/fe-queries.c b/src/fe-common/core/fe-queries.c
index 7599fb23..121417e4 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 = (!g_strcmp0(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/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..429e6dac 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;
@@ -185,7 +189,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 +268,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);
@@ -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/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index 96e03ceb..3bb43bf7 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);
@@ -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;
@@ -126,7 +127,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 +150,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 <key> [on|off|toggle] */
@@ -184,23 +183,24 @@ 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') 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)
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 */
diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c
index 4b914517..9822de1e 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);
}
}
@@ -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);
@@ -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)
@@ -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);
}
@@ -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 ");
diff --git a/src/fe-common/core/keyboard.c b/src/fe-common/core/keyboard.c
index 00454401..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;
@@ -118,7 +120,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;
}
@@ -135,7 +137,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);
@@ -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);
@@ -211,7 +217,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);
}
@@ -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, &copy)) {
+ if (!expand_key(rec->key, &copy, 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;
@@ -292,12 +310,18 @@ static int expand_key(const char *key, GSList **out)
}
last_hyphen = !last_hyphen;
} else if (*key == '^') {
+ expand_out_char(*out, '^');
+
/* ctrl-code */
- if (key[1] != '\0')
+ 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, '^');
- expand_out_char(*out, *key);
expand_out_char(*out, '-');
last_hyphen = FALSE; /* optional */
} else if (last_hyphen && i_isalpha(*key)) {
@@ -326,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;
@@ -340,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 (strcmp(rec->info->id, "key") == 0)
+ 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;
@@ -377,7 +402,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);
@@ -854,7 +879,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/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 },
diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c
index c0741cef..58e7b557 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) {
@@ -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';
}
@@ -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,
@@ -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/core/windows-layout.c b/src/fe-common/core/windows-layout.c
index 54d7dcbf..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);
@@ -143,7 +144,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 +161,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 +186,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 +196,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-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/dcc/fe-dcc-chat.c b/src/fe-common/irc/dcc/fe-dcc-chat.c
index 101aeb31..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);
}
@@ -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/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-common-irc.c b/src/fe-common/irc/fe-common-irc.c
index 72606263..4a3ef1d3 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);
@@ -71,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);
@@ -93,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();
@@ -118,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-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 d6c02d9f..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);
@@ -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);
@@ -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;
@@ -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-events.c b/src/fe-common/irc/fe-events.c
index 5cde9e4b..850174c5 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)
@@ -52,15 +53,19 @@ 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 (fe_channel_is_opchannel(server, target)) {
/* Hybrid 6 feature, send msg to all ops in channel */
- recoded = recode_in(SERVER(server), msg, target+1);
+ 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+1));
+ server, recoded, nick, addr, target);
} 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..a2737fc3 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 target;
+
+ statusmsg = g_hash_table_lookup(server->isupport, "statusmsg");
+
+ /* Hack: for bahamut 1.4 which sends neither STATUSMSG nor
+ * WALLCHOPS in 005, accept @#chan and @+#chan (but not +#chan) */
+ if (statusmsg == NULL && *target != '@')
+ return target;
+
+ 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 && 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-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-commands.c b/src/fe-common/irc/fe-irc-commands.c
index b380c214..11a911d2 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);
@@ -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;
@@ -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 0c83a531..40ca306d 100644
--- a/src/fe-common/irc/fe-irc-messages.c
+++ b/src/fe-common/irc/fe-irc-messages.c
@@ -36,32 +36,8 @@
#include "fe-queries.h"
#include "window-items.h"
-
-static const char *skip_target(IRC_SERVER_REC *server, const char *target)
-{
- int i = 0;
- const char *val, *chars;
-
- /* Quick check */
- if (server == NULL || server->prefix[(int)(unsigned char)*target] == 0)
- return target;
-
- /* 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 != '@')
- return target;
- chars = val ? val : "@+";
- for(i = 0; target[i] != '\0'; i++) {
- if (strchr(chars, target[i]) == NULL)
- break;
- };
-
- if(ischannel(target[i]))
- target += i;
-
- return target;
-}
+#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)
@@ -72,7 +48,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 */
@@ -95,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;
- nickmode = channel_get_nickmode(channel_find(server, target),
+ /* 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, cleantarget),
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,
@@ -117,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,
@@ -135,8 +122,8 @@ 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);
- if (ischannel(*target))
+ target = fe_channel_skip_prefix(IRC_SERVER(server), target);
+ if (server_ischannel(SERVER(server), target))
item = irc_channel_find(server, target);
else
item = irc_query_find(server, target);
@@ -146,7 +133,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);
@@ -160,12 +147,13 @@ 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);
+ target = fe_channel_skip_prefix(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;
@@ -174,15 +162,17 @@ 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
- item = privmsg_get_query(SERVER(server), nick, FALSE, level);
+ } else {
+ own = (!g_strcmp0(nick, server->nick));
+ item = privmsg_get_query(SERVER(server), own ? target : nick, FALSE, level);
+ }
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 */
@@ -195,11 +185,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);
@@ -208,7 +206,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);
}
@@ -221,7 +219,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 */
@@ -234,16 +232,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);
@@ -259,7 +257,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);
}
@@ -271,8 +269,8 @@ static void sig_message_irc_ctcp(IRC_SERVER_REC *server, const char *cmd,
const char *oldtarget;
oldtarget = target;
- target = skip_target(server, target);
- printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
+ 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);
}
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-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 <cert>] [-ssl_pkey <pkey>] [-ssl_pass <password>]
[-ssl_verify] [-ssl_cafile <cafile>] [-ssl_capath <capath>]
+ [-ssl_ciphers <list>]
[-auto | -noauto] [-network <network>] [-host <hostname>]
[-cmdspeed <ms>] [-cmdmax <count>] [-port <port>]
<address> [<port> [<password>]] */
@@ -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)
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index 6618edd7..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)
{
@@ -56,7 +58,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_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)
@@ -82,10 +89,12 @@ static void cmd_network_list(void)
}
/* SYNTAX: NETWORK ADD [-nick <nick>] [-user <user>] [-realname <name>]
- [-host <host>] [-usermode <mode>] [-autosendcmd <cmd>]
- [-querychans <count>] [-whois <count>] [-msgs <count>]
- [-kicks <count>] [-modes <count>]
- [-cmdspeed <ms>] [-cmdmax <count>] <name> */
+ [-host <host>] [-usermode <mode>] [-autosendcmd <cmd>]
+ [-querychans <count>] [-whois <count>] [-msgs <count>]
+ [-kicks <count>] [-modes <count>] [-cmdspeed <ms>]
+ [-cmdmax <count>] [-sasl_mechanism <mechanism>]
+ [-sasl_username <username>] [-sasl_password <password>]
+ <name> */
static void cmd_network_add(const char *data)
{
GHashTable *optlist;
@@ -112,6 +121,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 +160,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);
@@ -165,6 +185,8 @@ static void cmd_network_remove(const char *data)
if (rec == NULL)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NETWORK_NOT_FOUND, data);
else {
+ server_setup_remove_chatnet(data);
+ channel_setup_remove_chatnet(data);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NETWORK_REMOVED, data);
chatnet_remove(CHATNET(rec));
}
@@ -186,7 +208,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/fe-common/irc/fe-modes.c b/src/fe-common/irc/fe-modes.c
index 027d7a76..53e56c97 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);
@@ -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/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/fe-whois.c b/src/fe-common/irc/fe-whois.c
index 35f99375..117df120 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 <geert@irssi.org>
* Date: Wed Sep 15 20:17:24 CEST 2004
*/
@@ -134,8 +134,8 @@ static void event_whois_realhost(IRC_SERVER_REC *server, const char *data)
/* <yournick> real hostname <nick> <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) {
/* <yournick> <nick> :... from <hostname> */
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) {
/* <yournick> usermodes <nick> usermode */
printformat(server, nick, MSGLEVEL_CRAP,
IRCTXT_WHOIS_USERMODE, nick, usermode);
@@ -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);
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/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 309f3a68..306141ec 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -36,21 +36,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;
diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c
index 83b26e82..775e6044 100644
--- a/src/fe-text/gui-printtext.c
+++ b/src/fe-text/gui-printtext.c
@@ -230,16 +230,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/gui-readline.c b/src/fe-text/gui-readline.c
index 476a798b..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;
@@ -177,15 +176,15 @@ 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]))
+ 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 {
@@ -237,7 +236,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++;
@@ -392,9 +391,9 @@ static void sig_gui_key_pressed(gpointer keyp)
str[g_unichar_to_utf8(key, str)] = '\0';
}
- if (strcmp(str, "^") == 0) {
- /* change it as ^^ */
- str[1] = '^';
+ if (g_strcmp0(str, "^") == 0) {
+ /* change it as ^-, that is an invalid control char */
+ str[1] = '-';
str[2] = '\0';
}
@@ -1020,6 +1019,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);
diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c
index 77033d7a..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 <gc.h>
-#else
-# include <gc/gc.h>
-#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;
@@ -310,10 +294,7 @@ int main(int argc, char **argv)
{ "version", 'v', 0, G_OPTION_ARG_NONE, &version, "Display irssi version", NULL },
{ NULL }
};
-
-#ifdef USE_GC
- g_mem_set_vtable(&gc_mem_table);
-#endif
+ int loglev;
core_register_options();
fe_common_core_register_options();
@@ -352,6 +333,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,15 +342,13 @@ int main(int argc, char **argv)
return 1;
}
+ g_log_set_always_fatal(loglev);
textui_finish_init();
main_loop = g_main_new(TRUE);
/* 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();
diff --git a/src/fe-text/lastlog.c b/src/fe-text/lastlog.c
index 417eb484..166d2847 100644
--- a/src/fe-text/lastlog.c
+++ b/src/fe-text/lastlog.c
@@ -74,6 +74,25 @@ int cmd_options_get_level(const char *cmd, GHashTable *optlist)
return retlevel;
}
+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);
+ 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);
+
+ 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,
int start, int count, FILE *fhandle)
{
@@ -82,7 +101,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 +151,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 +221,9 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist,
g_string_prepend(line, timestamp);
}
+ if (date == TRUE)
+ prepend_date(window, rec, line);
+
/* write to file/window */
if (fhandle != NULL) {
fwrite(line->str, line->len, 1, fhandle);
@@ -223,7 +248,7 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist,
}
/* SYNTAX: LASTLOG [-] [-file <filename>] [-window <ref#|name>] [-new | -away]
- [-<level> -<level...>] [-clear] [-count] [-case]
+ [-<level> -<level...>] [-clear] [-count] [-case] [-date]
[-regexp | -word] [-before [<#>]] [-after [<#>]]
[-<# before+after>] [<pattern>] [<count> [<start>]] */
static void cmd_lastlog(const char *data)
@@ -285,7 +310,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)
diff --git a/src/fe-text/mainwindows-layout.c b/src/fe-text/mainwindows-layout.c
index 28fae924..020969e6 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);
@@ -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,
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,
diff --git a/src/fe-text/statusbar-config.c b/src/fe-text/statusbar-config.c
index deaa1b5d..a47a709e 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);
}
@@ -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/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,
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/term-terminfo.c b/src/fe-text/term-terminfo.c
index 29d3f7eb..27be904e 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();
@@ -520,15 +522,36 @@ 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 len, raw_len;
+ unichar tmp;
+ const char *ptr;
if (vcmove) term_move_real();
- len = strlen(str); /* FIXME utf8 or big5 */
+
+ len = 0;
+ raw_len = strlen(str);
+
+ /* The string length depends on the terminal encoding */
+
+ ptr = str;
+
+ 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;
+
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);
diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c
index d16987fe..60927f1a 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) },
-
- /* 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) },
+ /* Terminal size */
+ { "cols", "co", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, width) },
+ { "lines", "li", CAP_TYPE_INT, G_STRUCT_OFFSET(TERM_REC, height) },
- /* 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) },
+ /* 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) },
/* 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) },
-
- /* Beep */
- { "bel", "bl", CAP_TYPE_STR, G_STRUCT_OFFSET(TERM_REC, TI_bel) },
+ { "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) },
+
+ /* 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) */
@@ -498,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 */
@@ -523,7 +530,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 +549,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);
@@ -646,11 +660,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/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;
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/Makefile.am b/src/irc/core/Makefile.am
index 3db5cf0e..20caaeb1 100644
--- a/src/irc/core/Makefile.am
+++ b/src/irc/core/Makefile.am
@@ -26,6 +26,8 @@ libirc_core_a_SOURCES = \
irc-servers-reconnect.c \
irc-servers-setup.c \
irc-session.c \
+ irc-cap.c \
+ sasl.c \
lag.c \
massjoin.c \
modes.c \
@@ -48,6 +50,8 @@ pkginc_irc_core_HEADERS = \
irc-queries.h \
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/bans.c b/src/irc/core/bans.c
index d8d5d448..198fdc4a 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;
@@ -184,11 +184,11 @@ 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 (!ischannel(*channel)) cmd_param_error(CMDERR_NOT_JOINED);
+ 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 (strcmp(data, "*") != 0)
+ if (g_strcmp0(data, "*") != 0)
cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
/* /BAN * or /UNBAN * - ban/unban everyone */
nicks = (char *) data;
@@ -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;
@@ -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/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/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/irc-cap.c b/src/irc/core/irc-cap.c
new file mode 100644
index 00000000..5464e493
--- /dev/null
+++ b/src/irc/core/irc-cap.c
@@ -0,0 +1,192 @@
+/* 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"
+
+#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)) {
+ if (avail_caps > 0)
+ 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-channels.c b/src/irc/core/irc-channels.c
index e38cb98b..e775f530 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);
@@ -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);
@@ -172,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;
@@ -180,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-chatnets.c b/src/irc/core/irc-chatnets.c
index d757bf8d..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);
@@ -48,6 +51,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 = 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)
@@ -56,7 +63,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);
@@ -73,12 +80,23 @@ 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)
{
- if (IS_IRC_CHATNET(rec))
- g_free(rec->usermode);
+ 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-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-commands.c b/src/irc/core/irc-commands.c
index 7c3d3f5f..3cc105ba 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);
@@ -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);
@@ -191,7 +194,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);
@@ -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);
@@ -238,7 +245,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);
@@ -260,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 &&
@@ -279,24 +287,28 @@ 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))
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST |
+ PARAM_FLAG_STRIP_TRAILING_WS, &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);
+ 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';
}
- 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);
}
@@ -310,17 +322,18 @@ 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 (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 +422,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);
@@ -491,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;
@@ -502,8 +516,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);
}
@@ -810,7 +827,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) {
@@ -913,9 +930,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)
diff --git a/src/irc/core/irc-core.c b/src/irc/core/irc-core.c
index bf7386ad..a9221e02 100644
--- a/src/irc/core/irc-core.c
+++ b/src/irc/core/irc-core.c
@@ -26,6 +26,8 @@
#include "irc-chatnets.h"
#include "irc-channels.h"
#include "irc-queries.h"
+#include "irc-cap.h"
+#include "sasl.h"
#include "irc-servers-setup.h"
#include "channels-setup.h"
@@ -117,6 +119,8 @@ void irc_core_init(void)
lag_init();
netsplit_init();
irc_expandos_init();
+ cap_init();
+ sasl_init();
settings_check();
module_register("core", "irc");
@@ -126,6 +130,8 @@ void irc_core_deinit(void)
{
signal_emit("chat protocol deinit", 1, chat_protocol_find("IRC"));
+ sasl_deinit();
+ cap_deinit();
irc_expandos_deinit();
netsplit_deinit();
lag_deinit();
@@ -137,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-expandos.c b/src/irc/core/irc-expandos.c
index 5d2de503..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[100];
+ char hostname[HOST_NAME_MAX + 1];
ircserver = IRC_SERVER(server);
@@ -72,10 +76,36 @@ 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);;
}
+/* your hostname address (host) */
+static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
+{
+ IRC_SERVER_REC *ircserver;
+ char hostname[HOST_NAME_MAX + 1];
+ char **list;
+ char *hostname_split;
+
+ ircserver = IRC_SERVER(server);
+
+ *free_ret = TRUE;
+
+ /* prefer the _real_ /userhost reply */
+ if (ircserver != NULL && ircserver->userhost != NULL) {
+ list = g_strsplit(ircserver->userhost, "@", -1);
+ hostname_split = g_strdup(list[1]);
+ g_strfreev(list);
+ return hostname_split;
+ }
+
+ /* haven't received userhost reply yet. guess something */
+ if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0')
+ strcpy(hostname, "(none)");
+ return g_strdup(hostname);
+}
+
/* user mode in active server */
static char *expando_usermode(SERVER_REC *server, void *item, int *free_ret)
{
@@ -136,6 +166,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 +197,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);
diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c
index 5438509e..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') {
@@ -394,7 +370,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-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 *);
diff --git a/src/irc/core/irc-queries.c b/src/irc/core/irc-queries.c
index ac1a72a1..12861744 100644
--- a/src/irc/core/irc-queries.c
+++ b/src/irc/core/irc-queries.c
@@ -60,20 +60,20 @@ 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)
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-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;
}
diff --git a/src/irc/core/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c
index 5659991b..f425b587 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,
@@ -47,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,
@@ -79,6 +86,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() or cmd_network_add */
+ 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 missing 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 27878989..81f0c269 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -32,6 +32,10 @@
#include "irc-queries.h"
#include "irc-servers-setup.h"
#include "irc-servers.h"
+#include "irc-cap.h"
+#include "sasl.h"
+
+#include "channels-setup.h"
#include "channel-rejoin.h"
#include "servers-idle.h"
#include "servers-reconnect.h"
@@ -71,13 +75,20 @@ static int isnickflag_func(SERVER_REC *server, char flag)
static int ischannel_func(SERVER_REC *server, const char *data)
{
- if (*data == '@') {
- /* @#channel, @+#channel */
+ IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server;
+ 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 = "@+";
+
+ while (strchr(statusmsg, *data) != NULL)
data++;
- if (*data == '+' && ischannel(data[1]))
- return 1;
- }
- return ischannel(*data);
+
+ return strchr(chantypes, *data) != NULL;
}
static char **split_line(const SERVER_REC *server, const char *line,
@@ -85,6 +96,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 +115,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. */
@@ -213,6 +225,13 @@ static void server_init(IRC_SERVER_REC *server)
g_free(cmd);
}
+ 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') {
/* send password */
cmd = g_strdup_printf("PASS %s", conn->password);
@@ -313,6 +332,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);
@@ -408,7 +429,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,
@@ -587,32 +617,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) {
@@ -624,6 +681,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;
}
@@ -637,7 +695,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);
@@ -969,9 +1027,11 @@ 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", "");
+ 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);
diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h
index 7e4eeabf..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;
@@ -69,6 +73,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
diff --git a/src/irc/core/irc-session.c b/src/irc/core/irc-session.c
index 42d82734..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,8 +67,12 @@ 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(node, "isupport", NODE_TYPE_BLOCK);
+ isupport = config_node_section(config, node, "isupport", NODE_TYPE_BLOCK);
isupport_data.config = config;
isupport_data.node = isupport;
@@ -90,12 +96,21 @@ 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);
}
- 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/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)
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 ebaf4b8f..207461cc 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);
@@ -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);
@@ -835,14 +835,14 @@ 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;
}
- if (strcmp(target, "*") == 0) {
+ if (g_strcmp0(target, "*") == 0) {
if (!IS_IRC_CHANNEL(channel))
cmd_param_error(CMDERR_NOT_JOINED);
@@ -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/core/sasl.c b/src/irc/core/sasl.c
new file mode 100644
index 00000000..a04eaf45
--- /dev/null
+++ b/src/irc/core/sasl.c
@@ -0,0 +1,178 @@
+/*
+ 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"
+
+#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 */
+ 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)
+{
+ 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)
+{
+ char *params, *error;
+
+ /* Stop any pending timeout, if any */
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
+
+ params = event_get_params(data, 2, NULL, &error);
+
+ signal_emit("server sasl fail", 2, server, 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)
+{
+ 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)
+{
+ 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 */
+ 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 */
+ if (server->sasl_timeout != -1) {
+ g_source_remove(server->sasl_timeout);
+ server->sasl_timeout = -1;
+ }
+
+ switch (conn->sasl_mechanism) {
+ case SASL_MECHANISM_PLAIN:
+ /* 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 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');
+ 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 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);
+ signal_add_first("event 906", (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 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);
+ signal_remove("event 906", (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..0693989d
--- /dev/null
+++ b/src/irc/core/sasl.h
@@ -0,0 +1,34 @@
+/*
+ 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
+
+enum {
+ SASL_MECHANISM_NONE = 0,
+ SASL_MECHANISM_PLAIN,
+ SASL_MECHANISM_EXTERNAL,
+ SASL_MECHANISM_MAX
+};
+
+void sasl_init(void);
+void sasl_deinit(void);
+
+#endif
diff --git a/src/irc/core/servers-redirect.c b/src/irc/core/servers-redirect.c
index 34beaef6..aeb9c010 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;
}
@@ -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);
@@ -527,7 +529,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;
}
@@ -734,7 +736,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 +749,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);
diff --git a/src/irc/dcc/dcc-autoget.c b/src/irc/dcc/dcc-autoget.c
index 4768641b..de23a5d1 100644
--- a/src/irc/dcc/dcc-autoget.c
+++ b/src/irc/dcc/dcc-autoget.c
@@ -51,13 +51,13 @@ 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
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..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);
@@ -554,7 +555,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-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 6f0d5c81..7f35585e 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;
}
@@ -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);
@@ -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/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/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);
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/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..e39c21a6 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(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(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);
}
@@ -209,10 +209,10 @@ 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",
+ 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 33392285..dcc94e6b 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);
@@ -45,8 +47,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);
@@ -82,7 +84,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 +108,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;
}
@@ -126,6 +128,10 @@ 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(client->server, NULL, MSGLEVEL_CLIENTNOTICE,
+ "Proxy: Client %s:%d connected",
+ client->host, client->port);
client->connected = TRUE;
proxy_dump_data(client);
}
@@ -141,12 +147,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;
@@ -155,7 +161,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);
@@ -164,7 +170,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;
@@ -174,18 +180,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,17 +200,17 @@ 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;
}
/* 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 +218,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 +258,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;
@@ -262,7 +268,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) {
@@ -283,9 +289,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 +353,8 @@ static void sig_listen(LISTEN_REC *listen)
rec->listen = listen;
rec->handle = sendbuf;
rec->host = g_strdup(host);
- if (strcmp(listen->ircnet, "*") == 0) {
+ rec->port = port;
+ if (g_strcmp0(listen->ircnet, "*") == 0) {
rec->proxy_address = g_strdup("irc.proxy");
rec->server = servers == NULL ? NULL : IRC_SERVER(servers->data);
} else {
@@ -361,9 +368,10 @@ 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);
- printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
- "Proxy: Client connected from %s", rec->host);
+ 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);
}
static void sig_incoming(IRC_SERVER_REC *server, const char *line)
@@ -371,7 +379,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,
@@ -415,7 +423,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 +443,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,10 +470,10 @@ 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",
+ 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 +486,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);
@@ -634,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;
@@ -653,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)
@@ -676,6 +698,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;
@@ -697,6 +724,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 c8f47bdf..ce79e2b7 100644
--- a/src/irc/proxy/proxy.c
+++ b/src/irc/proxy/proxy.c
@@ -23,11 +23,60 @@
#include "settings.h"
#include "levels.h"
+#include "fe-common/core/printtext.h"
+
+/* 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,
+ "Proxy is currently disabled");
+ return;
+ }
+
+ 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);
+ }
+}
+
+/* SYNTAX: IRSSIPROXY */
+static void cmd_irssiproxy(const char *data, IRC_SERVER_REC *server, void *item)
+{
+ if (*data == '\0') {
+ cmd_irssiproxy_status(data, server);
+ return;
+ }
+
+ command_runsub("irssiproxy", 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! */
@@ -43,7 +92,14 @@ void irc_proxy_init(void)
"... to set them.");
}
- proxy_listen_init();
+ 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);
+
+ if (settings_get_bool("irssiproxy")) {
+ 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;
diff --git a/src/lib-config/get.c b/src/lib-config/get.c
index 2f1e90e1..a83686fd 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;
@@ -54,7 +54,6 @@ CONFIG_NODE *config_node_section_index(CONFIG_NODE *parent, const char *key,
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_NODE *parent, const char *key,
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_lookup_extended(rec->cache_nodes, node, NULL, NULL)) {
+ 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,9 +130,18 @@ 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(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;
@@ -109,6 +149,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_critical("Attempt to use non-list node `%s' as list. Corrupt config?", section);
+ return NULL;
+ }
+
/* save to cache */
str = g_strdup(section);
g_hash_table_insert(rec->cache, str, node);
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);
diff --git a/src/lib-config/set.c b/src/lib-config/set.c
index 61a101fb..7ca55871 100644
--- a/src/lib-config/set.c
+++ b/src/lib-config/set.c
@@ -104,8 +104,14 @@ 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)
+ if (g_strcmp0(node->value, value) == 0)
return;
g_free(node->value);
} else {
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/common/Irssi.pm b/src/perl/common/Irssi.pm
index a9f93bf0..e2d9f963 100644
--- a/src/perl/common/Irssi.pm
+++ b/src/perl/common/Irssi.pm
@@ -159,6 +159,8 @@ 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();
diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs
index 22a87384..db5c5f79 100644
--- a/src/perl/irc/Irc.xs
+++ b/src/perl/irc/Irc.xs
@@ -6,90 +6,91 @@ 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_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);
- 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 +98,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 +111,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 +134,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 +143,21 @@ 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, "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);
+ (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/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.";
+ }
}
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/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)
{
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[] = {
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");