diff --git a/.travis.yml b/.travis.yml index 35226645..46f58766 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +sudo: false language: perl perl: - "5.20-shrplib" @@ -7,28 +8,19 @@ env: - CC=clang - CC=gcc +addons: + apt: + packages: + - libperl-dev + - elinks + before_install: - - sudo apt-get update -qq - perl -V - - sudo apt-get build-dep -qq irssi - - sudo apt-get install -qq lynx install: true script: - - ./autogen.sh --with-proxy --with-bot --with-perl=module + - ./autogen.sh --with-proxy --with-bot --with-perl=module --prefix=$HOME/irssi-build - 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/configure.ac b/configure.ac index 7bcd3fe7..325b5e5d 100644 --- a/configure.ac +++ b/configure.ac @@ -7,6 +7,8 @@ AC_CONFIG_HEADERS([irssi-config.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([1.9 no-define foreign]) +AM_SILENT_RULES([yes]) + AM_MAINTAINER_MODE AC_PROG_CC diff --git a/docs/startup-HOWTO.html b/docs/startup-HOWTO.html index 30caf657..deff3116 100644 --- a/docs/startup-HOWTO.html +++ b/docs/startup-HOWTO.html @@ -391,7 +391,7 @@ messages window.

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

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/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/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/servers-reconnect.c b/src/core/servers-reconnect.c
index ae97ecd2..f419035b 100644
--- a/src/core/servers-reconnect.c
+++ b/src/core/servers-reconnect.c
@@ -420,8 +420,8 @@ static void cmd_reconnect(const char *data, SERVER_REC *server)
 			cmd_param_error(CMDERR_NOT_CONNECTED);
                 rec = reconnects->data;
 	} else {
-		if (g_ascii_strncasecmp(data, "RECON-", 6) == 0)
-			data += 6;
+		if (g_ascii_strncasecmp(tag, "RECON-", 6) == 0)
+			tag += 6;
 
 		tagnum = atoi(tag);
 		rec = tagnum <= 0 ? NULL : reconnect_find_tag(tagnum);
diff --git a/src/core/settings.c b/src/core/settings.c
index b34a5766..8e493124 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -59,7 +59,7 @@ static SETTINGS_REC *settings_get(const char *key, SettingType type)
 		g_warning("settings_get(%s) : not found", key);
 		return NULL;
 	}
-	if (type != -1 && rec->type != type) {
+	if (type != SETTING_TYPE_ANY && rec->type != type) {
 		g_warning("settings_get(%s) : invalid type", key);
 		return NULL;
 	}
@@ -85,7 +85,7 @@ settings_get_str_type(const char *key, SettingType type)
 
 const char *settings_get_str(const char *key)
 {
-	return settings_get_str_type(key, -1);
+	return settings_get_str_type(key, SETTING_TYPE_ANY);
 }
 
 int settings_get_int(const char *key)
@@ -163,6 +163,7 @@ char *settings_get_print(SETTINGS_REC *rec)
 	case SETTING_TYPE_TIME:
 	case SETTING_TYPE_LEVEL:
 	case SETTING_TYPE_SIZE:
+	case SETTING_TYPE_ANY:
 		value = g_strdup(settings_get_str(rec->key));
 		break;
 	}
@@ -380,10 +381,10 @@ SettingType settings_get_type(const char *key)
 {
 	SETTINGS_REC *rec;
 
-	g_return_val_if_fail(key != NULL, -1);
+	g_return_val_if_fail(key != NULL, SETTING_TYPE_ANY);
 
 	rec = g_hash_table_lookup(settings, key);
-	return rec == NULL ? -1 : rec->type;
+	return rec == NULL ? SETTING_TYPE_ANY : rec->type;
 }
 
 /* Get the record of the setting */
diff --git a/src/core/settings.h b/src/core/settings.h
index af00cc80..6f2cf129 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -7,7 +7,8 @@ typedef enum {
 	SETTING_TYPE_BOOLEAN,
 	SETTING_TYPE_TIME,
 	SETTING_TYPE_LEVEL,
-	SETTING_TYPE_SIZE
+	SETTING_TYPE_SIZE,
+	SETTING_TYPE_ANY
 } SettingType;
 
 typedef struct {
diff --git a/src/fe-common/core/completion.c b/src/fe-common/core/completion.c
index 312e417c..4461de92 100644
--- a/src/fe-common/core/completion.c
+++ b/src/fe-common/core/completion.c
@@ -362,8 +362,7 @@ static GList *completion_get_settings(const char *key, SettingType type)
 	for (tmp = sets; tmp != NULL; tmp = tmp->next) {
 		SETTINGS_REC *rec = tmp->data;
 
-		if ((type == -1 || rec->type == type) &&
-		    g_ascii_strncasecmp(rec->key, key, len) == 0)
+		if ((type == SETTING_TYPE_ANY || rec->type == type) && g_ascii_strncasecmp(rec->key, key, len) == 0)
 			complist = g_list_insert_sorted(complist, g_strdup(rec->key), (GCompareFunc) g_istr_cmp);
 	}
 	g_slist_free(sets);
@@ -682,7 +681,7 @@ static void sig_complete_set(GList **list, WINDOW_REC *window,
 
 	if (*line == '\0' ||
 	    !g_strcmp0("-clear", line) || !g_strcmp0("-default", line))
-		*list = completion_get_settings(word, -1);
+		*list = completion_get_settings(word, SETTING_TYPE_ANY);
 	else if (*line != '\0' && *word == '\0') {
 		SETTINGS_REC *rec = settings_get_record(line);
 		if (rec != NULL) {
diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index 9c370838..2627989d 100644
--- a/src/fe-common/core/fe-settings.c
+++ b/src/fe-common/core/fe-settings.c
@@ -126,7 +126,7 @@ static void cmd_set(char *data)
 			/* change the setting */
 			switch (rec->type) {
 			case SETTING_TYPE_BOOLEAN:
-                                if (clear)
+				if (clear)
 					settings_set_bool(key, FALSE);
 				else if (set_default)
 					settings_set_bool(key, rec->default_value.v_bool);
@@ -149,32 +149,30 @@ static void cmd_set(char *data)
 			case SETTING_TYPE_TIME:
 				if (!settings_set_time(key, clear ? "0" :
 						       set_default ? rec->default_value.v_string : value))
-					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
-						    TXT_INVALID_TIME);
+					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_INVALID_TIME);
 				break;
 			case SETTING_TYPE_LEVEL:
 				if (!settings_set_level(key, clear ? "" :
 							set_default ? rec->default_value.v_string : value))
-					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
-						    TXT_INVALID_LEVEL);
+					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_INVALID_LEVEL);
 				break;
 			case SETTING_TYPE_SIZE:
 				if (!settings_set_size(key, clear ? "0" :
 						       set_default ? rec->default_value.v_string : value))
-					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
-						    TXT_INVALID_SIZE);
+					printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_INVALID_SIZE);
+				break;
+			case SETTING_TYPE_ANY:
+				/* Unpossible! */
 				break;
 			}
 			signal_emit("setup changed", 0);
-			printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
-				    TXT_SET_TITLE, rec->section);
+			printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_SET_TITLE, rec->section);
 			set_print(rec);
 		} else
-			printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
-				    TXT_SET_UNKNOWN, key);
+			printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_SET_UNKNOWN, key);
 	}
 
-        cmd_params_free(free_arg);
+	cmd_params_free(free_arg);
 }
 
 /* SYNTAX: TOGGLE  [on|off|toggle] */
@@ -187,20 +185,21 @@ static void cmd_toggle(const char *data)
 	if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &key, &value))
 		return;
 
-        if (*key == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+	if (*key == '\0')
+		cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
 
 	type = settings_get_type(key);
-        if (type == -1)
+	if (type == SETTING_TYPE_ANY)
 		printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_SET_UNKNOWN, key);
 	else if (type != SETTING_TYPE_BOOLEAN)
 		printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_SET_NOT_BOOLEAN, key);
 	else {
 		set_boolean(key, *value != '\0' ? value : "TOGGLE");
-                set_print(settings_get_record(key));
+		set_print(settings_get_record(key));
 		signal_emit("setup changed", 0);
 	}
 
-        cmd_params_free(free_arg);
+	cmd_params_free(free_arg);
 }
 
 static int config_key_compare(CONFIG_NODE *node1, CONFIG_NODE *node2)
diff --git a/src/fe-common/core/keyboard.c b/src/fe-common/core/keyboard.c
index f138d4e2..fed7f9cb 100644
--- a/src/fe-common/core/keyboard.c
+++ b/src/fe-common/core/keyboard.c
@@ -31,6 +31,8 @@
 #include "fe-windows.h"
 #include "printtext.h"
 
+#define MAX_EXPAND_RECURSION 100
+
 GSList *keyinfos;
 static GHashTable *keys, *default_keys;
 
@@ -171,7 +173,7 @@ KEYINFO_REC *key_info_find(const char *id)
 	return NULL;
 }
 
-static int expand_key(const char *key, GSList **out);
+static int expand_key(const char *key, GSList **out, int *limit);
 
 #define expand_out_char(out, c) \
 	{ \
@@ -188,13 +190,17 @@ static int expand_key(const char *key, GSList **out);
 	  g_slist_free(out); out = NULL; \
 	}
 
-static int expand_combo(const char *start, const char *end, GSList **out)
+static int expand_combo(const char *start, const char *end, GSList **out, int *limit)
 {
         KEY_REC *rec;
 	KEYINFO_REC *info;
         GSList *tmp, *tmp2, *list, *copy, *newout;
 	char *str, *p;
 
+	if ((*limit)-- < 0) {
+		return FALSE;
+	}
+
 	if (start == end) {
 		/* single key */
 		expand_out_char(*out, *start);
@@ -229,7 +235,7 @@ static int expand_combo(const char *start, const char *end, GSList **out)
                 /* only one way to generate the combo, good */
                 rec = list->data;
 		g_slist_free(list);
-		return expand_key(rec->key, out);
+		return expand_key(rec->key, out, limit);
 	}
 
 	/* multiple ways to generate the combo -
@@ -244,7 +250,11 @@ static int expand_combo(const char *start, const char *end, GSList **out)
                         copy = g_slist_append(copy, g_string_new(str->str));
 		}
 
-		if (!expand_key(rec->key, ©)) {
+		if (!expand_key(rec->key, ©, limit)) {
+			if (*limit < 0) {
+				return FALSE;
+			}
+
 			/* illegal key combo, remove from list */
                         expand_out_free(copy);
 		} else {
@@ -254,7 +264,11 @@ static int expand_combo(const char *start, const char *end, GSList **out)
 
         rec = list->data;
 	g_slist_free(list);
-	if (!expand_key(rec->key, out)) {
+	if (!expand_key(rec->key, out, limit)) {
+		if (*limit < 0) {
+			return FALSE;
+		}
+
 		/* illegal key combo, remove from list */
 		expand_out_free(*out);
 	}
@@ -264,12 +278,16 @@ static int expand_combo(const char *start, const char *end, GSList **out)
 }
 
 /* Expand key code - returns TRUE if successful. */
-static int expand_key(const char *key, GSList **out)
+static int expand_key(const char *key, GSList **out, int *limit)
 {
 	GSList *tmp;
 	const char *start;
 	int last_hyphen;
 
+	if ((*limit)-- < 0) {
+		return FALSE;
+	}
+
 	/* meta-^W^Gf -> ^[-^W-^G-f */
         start = NULL; last_hyphen = TRUE;
 	for (; *key != '\0'; key++) {
@@ -279,7 +297,7 @@ static int expand_key(const char *key, GSList **out)
 				continue;
 			}
 
-			if (!expand_combo(start, key-1, out))
+			if (!expand_combo(start, key-1, out, limit))
                                 return FALSE;
 			expand_out_char(*out, '-');
                         start = NULL;
@@ -332,7 +350,7 @@ static int expand_key(const char *key, GSList **out)
 	}
 
 	if (start != NULL)
-		return expand_combo(start, key-1, out);
+		return expand_combo(start, key-1, out, limit);
 
 	for (tmp = *out; tmp != NULL; tmp = tmp->next) {
 		GString *str = tmp->data;
@@ -346,12 +364,13 @@ static int expand_key(const char *key, GSList **out)
 static void key_states_scan_key(const char *key, KEY_REC *rec)
 {
 	GSList *tmp, *out;
+	int limit = MAX_EXPAND_RECURSION;
 
 	if (g_strcmp0(rec->info->id, "key") == 0)
 		return;
 
         out = g_slist_append(NULL, g_string_new(NULL));
-	if (expand_key(key, &out)) {
+	if (expand_key(key, &out, &limit)) {
 		for (tmp = out; tmp != NULL; tmp = tmp->next) {
 			GString *str = tmp->data;
 
diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c
index dab6f57f..bb0af313 100644
--- a/src/fe-common/irc/fe-ircnet.c
+++ b/src/fe-common/irc/fe-ircnet.c
@@ -56,7 +56,12 @@ static void cmd_network_list(void)
 			g_string_append_printf(str, "autosendcmd: %s, ", rec->autosendcmd);
 		if (rec->usermode != NULL)
 			g_string_append_printf(str, "usermode: %s, ", rec->usermode);
-
+		if (rec->sasl_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)
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c
index 17a7c507..c7d06404 100644
--- a/src/fe-text/gui-entry.c
+++ b/src/fe-text/gui-entry.c
@@ -35,21 +35,21 @@ static unichar i_toupper(unichar c)
 {
 	if (term_type == TERM_TYPE_UTF8)
 		return g_unichar_toupper(c);
-	return (c >= 0 && c <= 255) ? toupper(c) : c;
+	return c <= 255 ? toupper(c) : c;
 }
 
 static unichar i_tolower(unichar c)
 {
 	if (term_type == TERM_TYPE_UTF8)
 		return g_unichar_tolower(c);
-	return (c >= 0 && c <= 255) ? tolower(c) : c;
+	return c <= 255 ? tolower(c) : c;
 }
 
 static int i_isalnum(unichar c)
 {
 	if (term_type == TERM_TYPE_UTF8)
 		return (g_unichar_isalnum(c) || mk_wcwidth(c) == 0);
-	return (c >= 0 && c <= 255) ? isalnum(c) : 0;
+	return c <= 255 ? isalnum(c) : 0;
 }
 
 GUI_ENTRY_REC *active_entry;
diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c
index 547d39c9..d8272df5 100644
--- a/src/fe-text/gui-printtext.c
+++ b/src/fe-text/gui-printtext.c
@@ -220,16 +220,15 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
 	get_colors(flags, &fg, &bg, &attr);
 
 	if (window == NULL) {
-                g_return_if_fail(next_xpos != -1);
+		g_return_if_fail(next_xpos != -1);
 
 		term_set_color2(root_window, attr, fg, bg);
 
 		term_move(root_window, next_xpos, next_ypos);
 		if (flags & GUI_PRINT_FLAG_CLRTOEOL)
 			term_clrtoeol(root_window);
-		term_addstr(root_window, str);
-		next_xpos += strlen(str); /* FIXME utf8 or big5 */
-                return;
+		next_xpos += term_addstr(root_window, str);
+		return;
 	}
 
 	lineinfo.level = dest == NULL ? 0 : dest->level;
diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c
index 6e169b93..96b8b386 100644
--- a/src/fe-text/gui-readline.c
+++ b/src/fe-text/gui-readline.c
@@ -1126,6 +1126,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);
+
 	key_bind("paste_start", "Bracketed paste start", "meta2-200~", "paste_start", (SIGNAL_FUNC) key_paste_start);
 
 	/* cursor movement */
diff --git a/src/fe-text/term-terminfo.c b/src/fe-text/term-terminfo.c
index 9376bda8..3582b9e4 100644
--- a/src/fe-text/term-terminfo.c
+++ b/src/fe-text/term-terminfo.c
@@ -522,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 692ce9c5..5f0a799e 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/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c
index d72f71dd..0796e0cb 100644
--- a/src/irc/core/irc-chatnets.c
+++ b/src/irc/core/irc-chatnets.c
@@ -35,10 +35,13 @@ void ircnet_create(IRC_CHATNET_REC *rec)
 
 static void sig_chatnet_read(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
 {
+	char *value;
+
 	if (!IS_IRC_CHATNET(rec))
 		return;
 
-	rec->usermode = g_strdup(config_node_get_str(node, "usermode", NULL));
+	value = config_node_get_str(node, "usermode", NULL);
+	rec->usermode = (value != NULL && *value != '\0') ? g_strdup(value) : NULL;
 
 	rec->max_cmds_at_once = config_node_get_int(node, "cmdmax", 0);
 	rec->cmd_queue_speed = config_node_get_int(node, "cmdspeed", 0);
diff --git a/src/irc/core/irc-expandos.c b/src/irc/core/irc-expandos.c
index 5d8150f0..62ef577a 100644
--- a/src/irc/core/irc-expandos.c
+++ b/src/irc/core/irc-expandos.c
@@ -27,6 +27,10 @@
 #include "irc-channels.h"
 #include "nicklist.h"
 
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 255
+#endif
+
 static char *last_join;
 
 /* last person to join a channel you are on */
@@ -56,7 +60,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
 {
 	IRC_SERVER_REC *ircserver;
 	const char *username;
-	char hostname[HOST_NAME_MAX];
+	char hostname[HOST_NAME_MAX + 1];
 
 	ircserver = IRC_SERVER(server);
 
@@ -80,7 +84,7 @@ static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret)
 static char *expando_hostname(SERVER_REC *server, void *item, int *free_ret)
 {
 	IRC_SERVER_REC *ircserver;
-	char hostname[HOST_NAME_MAX];
+	char hostname[HOST_NAME_MAX + 1];
 	char **list;
 	char *hostname_split;
 
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 bf1d2ddf..f425b587 100644
--- a/src/irc/core/irc-servers-setup.c
+++ b/src/irc/core/irc-servers-setup.c
@@ -48,12 +48,18 @@ static void sig_server_setup_fill_reconn(IRC_SERVER_CONNECT_REC *conn,
 
 static void sig_server_setup_fill_connect(IRC_SERVER_CONNECT_REC *conn)
 {
+	const char *value;
+
 	if (!IS_IRC_SERVER_CONNECT(conn))
 		return;
 
-	conn->alternate_nick = *settings_get_str("alternate_nick") != '\0' ?
-		g_strdup(settings_get_str("alternate_nick")) : NULL;
-        conn->usermode = g_strdup(settings_get_str("usermode"));
+	value = settings_get_str("alternate_nick");
+	conn->alternate_nick = (value != NULL && *value != '\0') ?
+		g_strdup(value) : NULL;
+
+	value = settings_get_str("usermode");
+	conn->usermode = (value != NULL && *value != '\0') ?
+		g_strdup(value) : NULL;
 }
 
 static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
diff --git a/src/irc/core/irc-session.c b/src/irc/core/irc-session.c
index ea65d8a5..18e8e5c7 100644
--- a/src/irc/core/irc-session.c
+++ b/src/irc/core/irc-session.c
@@ -28,6 +28,8 @@
 #include "irc-channels.h"
 #include "irc-nicklist.h"
 
+#include "sasl.h"
+
 struct _isupport_data { CONFIG_REC *config; CONFIG_NODE *node; };
 
 static void session_isupport_foreach(char *key, char *value, struct _isupport_data *data)
@@ -65,6 +67,10 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
 	config_node_set_str(config, node, "away_reason", server->away_reason);
 	config_node_set_bool(config, node, "emode_known", server->emode_known);
 
+	config_node_set_int(config, node, "sasl_mechanism", server->connrec->sasl_mechanism);
+	config_node_set_str(config, node, "sasl_username", server->connrec->sasl_username);
+	config_node_set_str(config, node, "sasl_password", server->connrec->sasl_password);
+
 	config_node_set_bool(config, node, "isupport_sent", server->isupport_sent);
 	isupport = config_node_section(config, node, "isupport", NODE_TYPE_BLOCK);
         isupport_data.config = config;
@@ -90,6 +96,15 @@ static void sig_session_restore_server(IRC_SERVER_REC *server,
 	server->emode_known = config_node_get_bool(node, "emode_known", FALSE);
 	server->isupport_sent = config_node_get_bool(node, "isupport_sent", FALSE);
 
+	server->connrec->sasl_mechanism = config_node_get_int(node, "sasl_mechanism", SASL_MECHANISM_NONE);
+	/* The fields below might have been filled when loading the chatnet
+	 * description from the config and we favor the content that's been saved
+	 * in the session file over that. */
+	g_free(server->connrec->sasl_username);
+	server->connrec->sasl_username = g_strdup(config_node_get_str(node, "sasl_username", NULL));
+	g_free(server->connrec->sasl_password);
+	server->connrec->sasl_password = g_strdup(config_node_get_str(node, "sasl_password", NULL));
+
 	if (server->isupport == NULL) {
 		server->isupport = g_hash_table_new((GHashFunc) g_istr_hash,
 						    (GCompareFunc) g_istr_equal);