summary refs log tree commit diff stats
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile.am20
-rw-r--r--src/common/cfgfiles.c96
-rw-r--r--src/common/cfgfiles.h6
-rw-r--r--src/common/chanopt.c18
-rw-r--r--src/common/common.vcxproj88
-rw-r--r--src/common/common.vcxproj.filters30
-rw-r--r--src/common/ctcp.c8
-rw-r--r--src/common/dbus/dbus-client.c4
-rw-r--r--src/common/dbus/dbus-plugin.c5
-rw-r--r--src/common/dbus/example.c2
-rw-r--r--src/common/dcc.c594
-rw-r--r--src/common/dcc.h27
-rw-r--r--src/common/fe.h4
-rw-r--r--src/common/hexchat.c153
-rw-r--r--src/common/hexchat.h46
-rw-r--r--src/common/history.c18
-rw-r--r--src/common/identd.c201
-rw-r--r--src/common/ignore.c43
-rw-r--r--src/common/inbound.c47
-rw-r--r--src/common/inet.h6
-rw-r--r--src/common/make-te.c4
-rw-r--r--src/common/make-te.vcxproj63
-rw-r--r--src/common/modes.c67
-rw-r--r--src/common/msproxy.c470
-rw-r--r--src/common/msproxy.h262
-rw-r--r--src/common/network.c209
-rw-r--r--src/common/network.h11
-rw-r--r--src/common/notify.c77
-rw-r--r--src/common/outbound.c441
-rw-r--r--src/common/outbound.h2
-rw-r--r--src/common/plugin-identd.c220
-rw-r--r--src/common/plugin-identd.h (renamed from src/common/identd.h)9
-rw-r--r--src/common/plugin-timer.c24
-rw-r--r--src/common/plugin.c117
-rw-r--r--src/common/plugin.h3
-rw-r--r--src/common/proto-irc.c27
-rw-r--r--src/common/server.c540
-rw-r--r--src/common/server.h3
-rw-r--r--src/common/servlist.c331
-rw-r--r--src/common/servlist.h1
-rw-r--r--src/common/ssl.c237
-rw-r--r--src/common/ssl.h4
-rw-r--r--src/common/text.c582
-rw-r--r--src/common/text.h10
-rw-r--r--src/common/tree.c7
-rw-r--r--src/common/tree.h2
-rw-r--r--src/common/url.c34
-rw-r--r--src/common/url.h2
-rw-r--r--src/common/userlist.c107
-rw-r--r--src/common/userlist.h2
-rw-r--r--src/common/util.c184
-rw-r--r--src/common/util.h6
52 files changed, 2012 insertions, 3462 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index e9255d0c..75aa12bc 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -1,5 +1,7 @@
 ## Process this file with automake to produce Makefile.in
 
+include $(top_srcdir)/m4/clang-analyze.am
+
 noinst_LIBRARIES = libhexchatcommon.a
 
 AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(top_srcdir)
@@ -14,17 +16,16 @@ EXTRA_DIST = \
 	hexchatc.h \
 	hexchat-plugin.h \
 	history.h \
-	identd.c \
 	ignore.h \
 	inbound.h \
 	inet.h \
 	make-te.c \
 	modes.h \
-	msproxy.h \
 	network.h \
 	notify.h \
 	outbound.h \
 	plugin.h \
+	plugin-identd.h \
 	plugin-timer.h \
 	proto-irc.h \
 	server.h \
@@ -32,6 +33,7 @@ EXTRA_DIST = \
 	ssl.h \
 	ssl.c	\
 	text.h \
+	typedef.h \
 	textenums.h \
 	textevents.h \
 	textevents.in \
@@ -44,10 +46,6 @@ if USE_OPENSSL
 ssl_c = ssl.c
 endif
 
-if USE_MSPROXY
-msproxy_c = msproxy.c
-endif
-
 if USE_DBUS
 dbusdir = dbus
 libhexchatcommon_a_LIBADD =				\
@@ -62,8 +60,8 @@ endif
 noinst_PROGRAMS = make-te
 
 libhexchatcommon_a_SOURCES = cfgfiles.c chanopt.c ctcp.c dcc.c hexchat.c \
-	history.c ignore.c inbound.c marshal.c modes.c $(msproxy_c) network.c notify.c \
-	outbound.c plugin.c plugin-timer.c proto-irc.c server.c servlist.c \
+	history.c ignore.c inbound.c marshal.c modes.c network.c notify.c \
+	outbound.c plugin.c plugin-identd.c plugin-timer.c proto-irc.c server.c servlist.c \
 	$(ssl_c) text.c tree.c url.c userlist.c util.c
 libhexchatcommon_a_CFLAGS = $(LIBPROXY_CFLAGS)
 
@@ -79,6 +77,12 @@ marshal.c: $(srcdir)/marshalers.list
 	$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=_hexchat_marshal --body $< > $@
 
 
+if DO_STATIC_ANALYSIS
+analyze_plists = $(libhexchatcommon_a_SOURCES:%.c=%.plist)
+all-local: $(analyze_plists)
+MOSTLYCLEANFILES = $(analyze_plists)
+endif
+
 BUILT_SOURCES = textenums.h textevents.h marshal.c marshal.h
 
 CLEANFILES = $(BUILT_SOURCES)
diff --git a/src/common/cfgfiles.c b/src/common/cfgfiles.c
index a8bd32f9..a49e17ae 100644
--- a/src/common/cfgfiles.c
+++ b/src/common/cfgfiles.c
@@ -39,7 +39,7 @@
 #endif
 
 #define DEF_FONT "Monospace 9"
-#define DEF_FONT_ALTER "Arial Unicode MS,Lucida Sans Unicode,MS Gothic,Unifont"
+#define DEF_FONT_ALTER "Arial Unicode MS,Segoe UI Emoji,Lucida Sans Unicode,Meiryo,Symbola,Unifont"
 
 const char * const languages[LANGUAGES_LENGTH] = {
 	"af", "sq", "am", "ast", "az", "eu", "be", "bg", "ca", "zh_CN",      /*  0 ..  9 */
@@ -57,15 +57,11 @@ list_addentry (GSList ** list, char *cmd, char *name)
 	size_t name_len;
 	size_t cmd_len = 1;
 
-	/* remove <2.8.0 stuff */
-	if (!strcmp (cmd, "away") && !strcmp (name, "BACK"))
-		return;
-
 	if (cmd)
 		cmd_len = strlen (cmd) + 1;
 	name_len = strlen (name) + 1;
 
-	pop = malloc (sizeof (struct popup) + cmd_len + name_len);
+	pop = g_malloc (sizeof (struct popup) + cmd_len + name_len);
 	pop->name = (char *) pop + sizeof (struct popup);
 	pop->cmd = pop->name + name_len;
 
@@ -137,13 +133,13 @@ list_loadconf (char *file, GSList ** list, char *defaultconf)
 		abort ();
 	}
 
-	ibuf = malloc (st.st_size);
+	ibuf = g_malloc (st.st_size);
 	read (fd, ibuf, st.st_size);
 	close (fd);
 
 	list_load_from_data (list, ibuf, st.st_size);
 
-	free (ibuf);
+	g_free (ibuf);
 }
 
 void
@@ -153,7 +149,7 @@ list_free (GSList ** list)
 	while (*list)
 	{
 		data = (void *) (*list)->data;
-		free (data);
+		g_free (data);
 		*list = g_slist_remove (*list, data);
 	}
 }
@@ -170,7 +166,7 @@ list_delentry (GSList ** list, char *name)
 		if (!g_ascii_strcasecmp (name, pop->name))
 		{
 			*list = g_slist_remove (*list, pop);
-			free (pop);
+			g_free (pop);
 			return 1;
 		}
 		alist = alist->next;
@@ -211,10 +207,10 @@ cfg_get_str (char *cfg, const char *var, char *dest, int dest_len)
 		while (*cfg != 0 && *cfg != '\n')
 			cfg++;
 		if (*cfg == 0)
-			return 0;
+			return NULL;
 		cfg++;
 		if (*cfg == 0)
-			return 0;
+			return NULL;
 	}
 }
 
@@ -224,18 +220,18 @@ cfg_put_str (int fh, char *var, char *value)
 	char buf[512];
 	int len;
 
-	snprintf (buf, sizeof buf, "%s = %s\n", var, value);
+	g_snprintf (buf, sizeof buf, "%s = %s\n", var, value);
 	len = strlen (buf);
 	return (write (fh, buf, len) == len);
 }
 
 int
-cfg_put_color (int fh, int r, int g, int b, char *var)
+cfg_put_color (int fh, guint16 r, guint16 g, guint16 b, char *var)
 {
 	char buf[400];
 	int len;
 
-	snprintf (buf, sizeof buf, "%s = %04x %04x %04x\n", var, r, g, b);
+	g_snprintf (buf, sizeof buf, "%s = %04hx %04hx %04hx\n", var, r, g, b);
 	len = strlen (buf);
 	return (write (fh, buf, len) == len);
 }
@@ -249,20 +245,20 @@ cfg_put_int (int fh, int value, char *var)
 	if (value == -1)
 		value = 1;
 
-	snprintf (buf, sizeof buf, "%s = %d\n", var, value);
+	g_snprintf (buf, sizeof buf, "%s = %d\n", var, value);
 	len = strlen (buf);
 	return (write (fh, buf, len) == len);
 }
 
 int
-cfg_get_color (char *cfg, char *var, int *r, int *g, int *b)
+cfg_get_color (char *cfg, char *var, guint16 *r, guint16 *g, guint16 *b)
 {
 	char str[128];
 
 	if (!cfg_get_str (cfg, var, str, sizeof (str)))
 		return 0;
 
-	sscanf (str, "%04x %04x %04x", r, g, b);
+	sscanf (str, "%04hx %04hx %04hx", r, g, b);
 	return 1;
 }
 
@@ -312,9 +308,7 @@ get_xdir (void)
 
 		if (portable_mode () || SHGetKnownFolderPath (&FOLDERID_RoamingAppData, 0, NULL, &roaming_path_wide) != S_OK)
 		{
-			char *path;
-
-			path = g_win32_get_package_installation_directory_of_module (NULL);
+			char *path = g_win32_get_package_installation_directory_of_module (NULL);
 			if (path)
 			{
 				xdir = g_build_filename (path, "config", NULL);
@@ -440,6 +434,7 @@ const struct prefs vars[] =
 	{"gui_tab_dots", P_OFFINT (hex_gui_tab_dots), TYPE_BOOL},
 	{"gui_tab_icons", P_OFFINT (hex_gui_tab_icons), TYPE_BOOL},
 	{"gui_tab_layout", P_OFFINT (hex_gui_tab_layout), TYPE_INT},
+	{"gui_tab_middleclose", P_OFFINT (hex_gui_tab_middleclose), TYPE_BOOL},
 	{"gui_tab_newtofront", P_OFFINT (hex_gui_tab_newtofront), TYPE_INT},
 	{"gui_tab_pos", P_OFFINT (hex_gui_tab_pos), TYPE_INT},
 	{"gui_tab_scrollchans", P_OFFINT (hex_gui_tab_scrollchans), TYPE_BOOL},
@@ -482,11 +477,11 @@ const struct prefs vars[] =
 	{"gui_win_width", P_OFFINT (hex_gui_win_width), TYPE_INT},
 
 	{"identd", P_OFFINT (hex_identd), TYPE_BOOL},
+	{"identd_port", P_OFFINT (hex_identd_port), TYPE_INT},
 
 	{"input_balloon_chans", P_OFFINT (hex_input_balloon_chans), TYPE_BOOL},
 	{"input_balloon_hilight", P_OFFINT (hex_input_balloon_hilight), TYPE_BOOL},
 	{"input_balloon_priv", P_OFFINT (hex_input_balloon_priv), TYPE_BOOL},
-	{"input_balloon_time", P_OFFINT (hex_input_balloon_time), TYPE_INT},
 	{"input_beep_chans", P_OFFINT (hex_input_beep_chans), TYPE_BOOL},
 	{"input_beep_hilight", P_OFFINT (hex_input_beep_hilight), TYPE_BOOL},
 	{"input_beep_priv", P_OFFINT (hex_input_beep_priv), TYPE_BOOL},
@@ -590,10 +585,10 @@ const struct prefs vars[] =
 	{0, 0, 0},
 };
 
-static char *
+static const char *
 convert_with_fallback (const char *str, const char *fallback)
 {
-	char *utf;
+	const char *utf;
 
 #ifndef WIN32
 	/* On non-Windows, g_get_user_name and g_get_real_name return a string in system locale, so convert it to utf-8. */
@@ -652,7 +647,7 @@ get_default_language (void)
 
 	if (lang_no >= 0)
 	{
-		free (lang);
+		g_free (lang);
 		return lang_no;
 	}
 
@@ -661,7 +656,7 @@ get_default_language (void)
 
 	lang_no = find_language_number (lang);
 
-	free (lang);
+	g_free (lang);
 
 	return lang_no >= 0 ? lang_no : find_language_number ("en");
 }
@@ -703,8 +698,8 @@ get_default_spell_languages (void)
 				}
 			}
 		}
-		if (last != NULL)
-			g_free(last);
+
+		g_free (last);
 
 		if (lang_list[0])
 			return g_strdup (ret);
@@ -765,6 +760,7 @@ load_default_config(void)
 	prefs.hex_gui_tab_chans = 1;
 	prefs.hex_gui_tab_dialogs = 1;
 	prefs.hex_gui_tab_icons = 1;
+	prefs.hex_gui_tab_middleclose = 1;
 	prefs.hex_gui_tab_server = 1;
 	prefs.hex_gui_tab_sort = 1;
 	prefs.hex_gui_topicbar = 1;
@@ -776,7 +772,6 @@ load_default_config(void)
 	prefs.hex_gui_ulist_resizable = 1;
 	prefs.hex_gui_ulist_style = 1;
 	prefs.hex_gui_win_save = 1;
-	prefs.hex_identd = 1;
 	prefs.hex_input_flash_hilight = 1;
 	prefs.hex_input_flash_priv = 1;
 	prefs.hex_input_tray_hilight = 1;
@@ -832,7 +827,6 @@ load_default_config(void)
 	prefs.hex_gui_ulist_pos = 3;
 	prefs.hex_gui_win_height = 400;
 	prefs.hex_gui_win_width = 640;
-	prefs.hex_input_balloon_time = 20;
 	prefs.hex_irc_ban_type = 1;
 	prefs.hex_irc_join_delay = 5;
 	prefs.hex_net_reconnect_delay = 10;
@@ -847,7 +841,7 @@ load_default_config(void)
 #ifdef WIN32
 	if (portable_mode () || SHGetKnownFolderPath (&FOLDERID_Downloads, 0, NULL, &roaming_path_wide) != S_OK)
 	{
-		snprintf (prefs.hex_dcc_dir, sizeof (prefs.hex_dcc_dir), "%s\\downloads", get_xdir ());
+		g_snprintf (prefs.hex_dcc_dir, sizeof (prefs.hex_dcc_dir), "%s\\downloads", get_xdir ());
 	}
 	else
 	{
@@ -861,34 +855,36 @@ load_default_config(void)
 #else
 	if (g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD))
 	{
-		strcpy (prefs.hex_dcc_dir, g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD));
+		safe_strcpy (prefs.hex_dcc_dir, g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD), sizeof(prefs.hex_dcc_dir));
 	}
 	else
 	{
-		strcpy (prefs.hex_dcc_dir, g_build_filename (g_get_home_dir (), "Downloads", NULL));
+		char *download_dir = g_build_filename (g_get_home_dir (), "Downloads", NULL);
+		safe_strcpy (prefs.hex_dcc_dir, download_dir, sizeof(prefs.hex_dcc_dir));
+		g_free (download_dir);
 	}
 #endif
 	strcpy (prefs.hex_gui_ulist_doubleclick, "QUERY %s");
 	strcpy (prefs.hex_input_command_char, "/");
-	strcpy (prefs.hex_irc_logmask, g_build_filename ("%n", "%c.log", NULL));
-	strcpy (prefs.hex_irc_nick1, username);
-	strcpy (prefs.hex_irc_nick2, username);
-	strcat (prefs.hex_irc_nick2, "_");
-	strcpy (prefs.hex_irc_nick3, username);
-	strcat (prefs.hex_irc_nick3, "__");
+	strcpy (prefs.hex_irc_logmask, "%n"G_DIR_SEPARATOR_S"%c.log");
+	safe_strcpy (prefs.hex_irc_nick1, username, sizeof(prefs.hex_irc_nick1));
+	safe_strcpy (prefs.hex_irc_nick2, username, sizeof(prefs.hex_irc_nick2));
+	g_strlcat (prefs.hex_irc_nick2, "_", sizeof(prefs.hex_irc_nick2));
+	safe_strcpy (prefs.hex_irc_nick3, username, sizeof(prefs.hex_irc_nick3));
+	g_strlcat (prefs.hex_irc_nick3, "__", sizeof(prefs.hex_irc_nick3));
 	strcpy (prefs.hex_irc_no_hilight, "NickServ,ChanServ,InfoServ,N,Q");
-	strcpy (prefs.hex_irc_part_reason, _("Leaving"));
-	strcpy (prefs.hex_irc_quit_reason, prefs.hex_irc_part_reason);
-	strcpy (prefs.hex_irc_real_name, realname);
-	strcpy (prefs.hex_irc_user_name, username);
+	safe_strcpy (prefs.hex_irc_part_reason, _("Leaving"), sizeof(prefs.hex_irc_part_reason));
+	safe_strcpy (prefs.hex_irc_quit_reason, prefs.hex_irc_part_reason, sizeof(prefs.hex_irc_quit_reason));
+	safe_strcpy (prefs.hex_irc_real_name, realname, sizeof(prefs.hex_irc_real_name));
+	safe_strcpy (prefs.hex_irc_user_name, username, sizeof(prefs.hex_irc_user_name));
 	strcpy (prefs.hex_stamp_log_format, "%b %d %H:%M:%S ");
 	strcpy (prefs.hex_stamp_text_format, "[%H:%M:%S] ");
 
 	font = fe_get_default_font ();
 	if (font)
 	{
-		strcpy (prefs.hex_text_font, font);
-		strcpy (prefs.hex_text_font_main, font);
+		safe_strcpy (prefs.hex_text_font, font, sizeof(prefs.hex_text_font));
+		safe_strcpy (prefs.hex_text_font_main, font, sizeof(prefs.hex_text_font_main));
 	}
 	else
 	{
@@ -898,7 +894,7 @@ load_default_config(void)
 
 	strcpy (prefs.hex_text_font_alternative, DEF_FONT_ALTER);
 	langs = get_default_spell_languages ();
-	strcpy (prefs.hex_text_spell_langs, langs);
+	safe_strcpy (prefs.hex_text_spell_langs, langs, sizeof(prefs.hex_text_spell_langs));
 
 
 	/* private variables */
@@ -1228,7 +1224,7 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 				if (erase || *val)
 				{
 					/* save the previous value until we print it out */
-					prev_string = (char*) malloc (vars[i].len + 1);
+					prev_string = g_malloc (vars[i].len + 1);
 					strncpy (prev_string, (char *) &prefs + vars[i].offset, vars[i].len);
 
 					/* update the variable */
@@ -1240,7 +1236,7 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 						PrintTextf (sess, "%s set to: %s (was: %s)\n", var, (char *) &prefs + vars[i].offset, prev_string);
 					}
 
-					free (prev_string);
+					g_free (prev_string);
 				}
 				else
 				{
@@ -1315,7 +1311,7 @@ cmd_set (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 }
 
 int
-hexchat_open_file (char *file, int flags, int mode, int xof_flags)
+hexchat_open_file (const char *file, int flags, int mode, int xof_flags)
 {
 	char *buf;
 	int fd;
@@ -1351,7 +1347,7 @@ hexchat_fopen_file (const char *file, const char *mode, int xof_flags)
 	FILE *fh;
 
 	if (xof_flags & XOF_FULLPATH)
-		return fopen (file, mode);
+		return g_fopen (file, mode);
 
 	buf = g_build_filename (get_xdir (), file, NULL);
 	fh = g_fopen (buf, mode);
diff --git a/src/common/cfgfiles.h b/src/common/cfgfiles.h
index 8b996ca0..b421884a 100644
--- a/src/common/cfgfiles.h
+++ b/src/common/cfgfiles.h
@@ -34,8 +34,8 @@ int cfg_get_bool (char *var);
 int cfg_get_int_with_result (char *cfg, char *var, int *result);
 int cfg_get_int (char *cfg, char *var);
 int cfg_put_int (int fh, int value, char *var);
-int cfg_get_color (char *cfg, char *var, int *r, int *g, int *b);
-int cfg_put_color (int fh, int r, int g, int b, char *var);
+int cfg_get_color (char *cfg, char *var, guint16 *r, guint16 *g, guint16 *b);
+int cfg_put_color (int fh, guint16 r, guint16 g, guint16 b, char *var);
 char *get_xdir (void);
 int check_config_dir (void);
 void load_default_config (void);
@@ -48,7 +48,7 @@ void list_loadconf (char *file, GSList ** list, char *defaultconf);
 int list_delentry (GSList ** list, char *name);
 void list_addentry (GSList ** list, char *cmd, char *name);
 int cmd_set (session *sess, char *tbuf, char *word[], char *word_eol[]);
-int hexchat_open_file (char *file, int flags, int mode, int xof_flags);
+int hexchat_open_file (const char *file, int flags, int mode, int xof_flags);
 FILE *hexchat_fopen_file (const char *file, const char *mode, int xof_flags);
 
 #define XOF_DOMODE 1
diff --git a/src/common/chanopt.c b/src/common/chanopt.c
index 820a31fb..7bd66b4a 100644
--- a/src/common/chanopt.c
+++ b/src/common/chanopt.c
@@ -119,7 +119,7 @@ chanopt_command (session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (!quiet)
 		PrintTextf (sess, "\002Network\002: %s \002Channel\002: %s\n",
 						sess->server->network ? server_get_network (sess->server, TRUE) : _("<none>"),
-						sess->channel[0] ? sess->channel : _("<none>"));
+						sess->session_name[0] ? sess->session_name : _("<none>"));
 
 	while (i < sizeof (chanopt) / sizeof (channel_options))
 	{
@@ -208,7 +208,7 @@ chanopt_find (char *network, char *channel, gboolean add_new)
 		return NULL;
 
 	/* allocate a new one */
-	co = g_malloc0 (sizeof (chanopt_in_memory));
+	co = g_new0 (chanopt_in_memory, 1);
 	co->channel = g_strdup (channel);
 	co->network = g_strdup (network);
 
@@ -298,7 +298,7 @@ chanopt_load (session *sess)
 	chanopt_in_memory *co;
 	char *network;
 
-	if (sess->channel[0] == 0)
+	if (sess->session_name[0] == 0)
 		return;
 
 	network = server_get_network (sess->server, FALSE);
@@ -311,7 +311,7 @@ chanopt_load (session *sess)
 		chanopt_load_all ();
 	}
 
-	co = chanopt_find (network, sess->channel, FALSE);
+	co = chanopt_find (network, sess->session_name, FALSE);
 	if (!co)
 		return;
 
@@ -334,7 +334,7 @@ chanopt_save (session *sess)
 	chanopt_in_memory *co;
 	char *network;
 
-	if (sess->channel[0] == 0)
+	if (sess->session_name[0] == 0)
 		return;
 
 	network = server_get_network (sess->server, FALSE);
@@ -343,7 +343,7 @@ chanopt_save (session *sess)
 
 	/* 2. reconcile sess with what we loaded from disk */
 
-	co = chanopt_find (network, sess->channel, TRUE);
+	co = chanopt_find (network, sess->session_name, TRUE);
 
 	i = 0;
 	while (i < sizeof (chanopt) / sizeof (channel_options))
@@ -368,10 +368,10 @@ chanopt_save_one_channel (chanopt_in_memory *co, int fh)
 	char buf[256];
 	guint8 val;
 
-	snprintf (buf, sizeof (buf), "%s = %s\n", "network", co->network);
+	g_snprintf (buf, sizeof (buf), "%s = %s\n", "network", co->network);
 	write (fh, buf, strlen (buf));
 
-	snprintf (buf, sizeof (buf), "%s = %s\n", "channel", co->channel);
+	g_snprintf (buf, sizeof (buf), "%s = %s\n", "channel", co->channel);
 	write (fh, buf, strlen (buf));
 
 	i = 0;
@@ -380,7 +380,7 @@ chanopt_save_one_channel (chanopt_in_memory *co, int fh)
 		val = G_STRUCT_MEMBER (guint8, co, chanopt[i].offset);
 		if (val != SET_DEFAULT)
 		{
-			snprintf (buf, sizeof (buf), "%s = %d\n", chanopt[i].name, val);
+			g_snprintf (buf, sizeof (buf), "%s = %d\n", chanopt[i].name, val);
 			write (fh, buf, strlen (buf));
 		}
 		i++;
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
index 02449340..28a4da11 100644
--- a/src/common/common.vcxproj
+++ b/src/common/common.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>StaticLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -20,16 +21,15 @@
     <ClInclude Include="dcc.h" />

     <ClInclude Include="fe.h" />

     <ClInclude Include="history.h" />

-    <ClInclude Include="identd.h" />

     <ClInclude Include="ignore.h" />

     <ClInclude Include="inbound.h" />

     <ClInclude Include="inet.h" />

-    <ClInclude Include="marshal.h" />

+    <ClInclude Include="$(HexChatLib)marshal.h" />

     <ClInclude Include="modes.h" />

-    <ClInclude Include="msproxy.h" />

     <ClInclude Include="network.h" />

     <ClInclude Include="notify.h" />

     <ClInclude Include="outbound.h" />

+    <ClInclude Include="plugin-identd.h" />

     <ClInclude Include="plugin-timer.h" />

     <ClInclude Include="plugin.h" />

     <ClInclude Include="proto-irc.h" />

@@ -37,8 +37,8 @@
     <ClInclude Include="servlist.h" />

     <ClInclude Include="ssl.h" />

     <ClInclude Include="text.h" />

-    <ClInclude Include="textenums.h" />

-    <ClInclude Include="textevents.h" />

+    <ClInclude Include="$(HexChatLib)textenums.h" />

+    <ClInclude Include="$(HexChatLib)textevents.h" />

     <ClInclude Include="tree.h" />

     <ClInclude Include="typedef.h" />

     <ClInclude Include="url.h" />

@@ -54,12 +54,11 @@
     <ClCompile Include="ctcp.c" />

     <ClCompile Include="dcc.c" />

     <ClCompile Include="history.c" />

-    <ClCompile Include="identd.c" />

+    <ClCompile Include="plugin-identd.c" />

     <ClCompile Include="ignore.c" />

     <ClCompile Include="inbound.c" />

-    <ClCompile Include="marshal.c" />

+    <ClCompile Include="$(HexChatLib)marshal.c" />

     <ClCompile Include="modes.c" />

-    <ClCompile Include="msproxy.c" />

     <ClCompile Include="network.c" />

     <ClCompile Include="notify.c" />

     <ClCompile Include="outbound.c" />

@@ -78,7 +77,7 @@
   </ItemGroup>

   <ItemGroup>

     <None Include="..\..\win32\config.h.tt" />

-    <ClInclude Include="..\..\config.h" />

+    <ClInclude Include="$(HexChatLib)config.h" />

   </ItemGroup>

   <PropertyGroup Label="Globals">

     <ProjectGuid>{87554B59-006C-4D94-9714-897B27067BA3}</ProjectGuid>

@@ -86,85 +85,36 @@
     <RootNamespace>common</RootNamespace>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

-    <ConfigurationType>StaticLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-    <Import Project="..\..\win32\hexchat.props" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-    <Import Project="..\..\win32\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+  <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  <Import Project="..\..\win32\hexchat.props" />

+  <PropertyGroup>

+    <OutDir>$(HexChatLib)</OutDir>

   </PropertyGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(HexChatLib);$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

-    <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-    </Link>

   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(HexChatLib);$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

       <DisableSpecificWarnings>4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>

     </ClCompile>

-    <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-    </Link>

   </ItemDefinitionGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

   <ItemDefinitionGroup>

     <PreBuildEvent>

       <Command><![CDATA[

 SET SOLUTIONDIR=$(SolutionDir)..\

-powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\win32\config.h.tt" "$(SolutionDir)..\config.h"

-"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --header "$(ProjectDir)marshalers.list" > "$(ProjectDir)marshal.h"

-"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --body "$(ProjectDir)marshalers.list" > "$(ProjectDir)marshal.c"

+"$(HexChatLib)make-te.exe" < "$(ProjectDir)textevents.in" > "$(HexChatLib)textevents.h" 2> "$(HexChatLib)textenums.h"

+powershell -File "$(SolutionDir)..\win32\version-template.ps1" "$(SolutionDir)..\win32\config.h.tt" "$(HexChatLib)config.h"

+"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --header "$(ProjectDir)marshalers.list" > "$(HexChatLib)marshal.h"

+"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --body "$(ProjectDir)marshalers.list" > "$(HexChatLib)marshal.c"

 

       ]]></Command>

     </PreBuildEvent>

   </ItemDefinitionGroup>

-</Project>
\ No newline at end of file
+</Project>

diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters
index c2d0ce5d..79e64cb4 100644
--- a/src/common/common.vcxproj.filters
+++ b/src/common/common.vcxproj.filters
@@ -29,9 +29,6 @@
     <ClInclude Include="history.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="identd.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

     <ClInclude Include="ignore.h">

       <Filter>Header Files</Filter>

     </ClInclude>

@@ -44,9 +41,6 @@
     <ClInclude Include="modes.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="msproxy.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

     <ClInclude Include="network.h">

       <Filter>Header Files</Filter>

     </ClInclude>

@@ -77,10 +71,10 @@
     <ClInclude Include="text.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="textenums.h">

+    <ClInclude Include="$(HexChatLib)textenums.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="textevents.h">

+    <ClInclude Include="$(HexChatLib)textevents.h">

       <Filter>Header Files</Filter>

     </ClInclude>

     <ClInclude Include="tree.h">

@@ -104,13 +98,16 @@
     <ClInclude Include="hexchat-plugin.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="..\..\config.h">

+    <ClInclude Include="$(HexChatLib)config.h">

       <Filter>Header Files</Filter>

     </ClInclude>

     <ClInclude Include="typedef.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="marshal.h">

+    <ClInclude Include="$(HexChatLib)marshal.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="plugin-identd.h">

       <Filter>Header Files</Filter>

     </ClInclude>

   </ItemGroup>

@@ -130,9 +127,6 @@
     <ClCompile Include="history.c">

       <Filter>Source Files</Filter>

     </ClCompile>

-    <ClCompile Include="identd.c">

-      <Filter>Source Files</Filter>

-    </ClCompile>

     <ClCompile Include="ignore.c">

       <Filter>Source Files</Filter>

     </ClCompile>

@@ -142,9 +136,6 @@
     <ClCompile Include="modes.c">

       <Filter>Source Files</Filter>

     </ClCompile>

-    <ClCompile Include="msproxy.c">

-      <Filter>Source Files</Filter>

-    </ClCompile>

     <ClCompile Include="network.c">

       <Filter>Source Files</Filter>

     </ClCompile>

@@ -190,11 +181,14 @@
     <ClCompile Include="hexchat.c">

       <Filter>Source Files</Filter>

     </ClCompile>

-    <ClCompile Include="marshal.c">

+    <ClCompile Include="$(HexChatLib)marshal.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="plugin-identd.c">

       <Filter>Source Files</Filter>

     </ClCompile>

   </ItemGroup>

   <ItemGroup>

     <None Include="..\..\win32\config.h.tt" />

   </ItemGroup>

-</Project>
\ No newline at end of file
+</Project>

diff --git a/src/common/ctcp.c b/src/common/ctcp.c
index b4fb55b7..bf0a8e7f 100644
--- a/src/common/ctcp.c
+++ b/src/common/ctcp.c
@@ -44,12 +44,12 @@ ctcp_reply (session *sess, char *nick, char *word[], char *word_eol[],
 {
 	char tbuf[4096];	/* can receive 2048 from IRC, so this is enough */
 
-	conf = strdup (conf);
+	conf = g_strdup (conf);
 	/* process %C %B etc */
 	check_special_chars (conf, TRUE);
 	auto_insert (tbuf, sizeof (tbuf), conf, word, word_eol, "", "", word_eol[5],
 					 server_get_network (sess->server, TRUE), "", "", nick, "");
-	free (conf);
+	g_free (conf);
 	handle_command (sess, tbuf, FALSE);
 }
 
@@ -139,10 +139,10 @@ ctcp_handle (session *sess, char *to, char *nick, char *ip,
 	if (!g_ascii_strcasecmp (msg, "VERSION") && !prefs.hex_irc_hide_version)
 	{
 #ifdef WIN32
-		snprintf (outbuf, sizeof (outbuf), "VERSION HexChat "PACKAGE_VERSION" [x%d] / %s",
+		g_snprintf (outbuf, sizeof (outbuf), "VERSION HexChat "PACKAGE_VERSION" [x%d] / %s",
 					 get_cpu_arch (), get_sys_str (1));
 #else
-		snprintf (outbuf, sizeof (outbuf), "VERSION HexChat "PACKAGE_VERSION" / %s",
+		g_snprintf (outbuf, sizeof (outbuf), "VERSION HexChat "PACKAGE_VERSION" / %s",
 					 get_sys_str (1));
 #endif
 		serv->p_nctcp (serv, nick, outbuf);
diff --git a/src/common/dbus/dbus-client.c b/src/common/dbus/dbus-client.c
index e507883d..bbbe10e8 100644
--- a/src/common/dbus/dbus-client.c
+++ b/src/common/dbus/dbus-client.c
@@ -19,6 +19,8 @@
  * xclaesse@gmail.com
  */
 
+#include "config.h"
+
 #define GLIB_DISABLE_DEPRECATION_WARNINGS
 #include <dbus/dbus-glib.h>
 #include "dbus-client.h"
@@ -91,7 +93,7 @@ hexchat_remote (void)
 	g_object_unref (dbus);
 
 	if (!hexchat_running) {
-		//dbus_g_connection_unref (connection);
+		/* dbus_g_connection_unref (connection); */
 		return;
 	}
 
diff --git a/src/common/dbus/dbus-plugin.c b/src/common/dbus/dbus-plugin.c
index ee8accfe..1afd9ef0 100644
--- a/src/common/dbus/dbus-plugin.c
+++ b/src/common/dbus/dbus-plugin.c
@@ -26,6 +26,7 @@
 #include <dbus/dbus-glib-lowlevel.h>
 #include <glib/gi18n.h>
 #include "hexchat-plugin.h"
+#include "dbus-plugin.h"
 
 #define PNAME _("remote access")
 #define PDESC _("plugin for remote access using DBUS")
@@ -365,6 +366,7 @@ remote_object_connect (RemoteObject *obj,
 	static guint count = 0;
 	char *sender, *path;
 	RemoteObject *remote_object;
+	gchar count_buffer[15];
 	
 	sender = dbus_g_method_get_sender (context);
 	remote_object = g_hash_table_lookup (clients, sender);
@@ -373,7 +375,8 @@ remote_object_connect (RemoteObject *obj,
 		g_free (sender);
 		return TRUE;
 	}
-	path = g_build_filename (DBUS_OBJECT_PATH, count++, NULL);
+	g_snprintf(count_buffer, sizeof(count_buffer), "%u", count++);
+	path = g_build_filename (DBUS_OBJECT_PATH, count_buffer, NULL);
 	remote_object = g_object_new (REMOTE_TYPE_OBJECT, NULL);
 	remote_object->dbus_path = path;
 	remote_object->filename = g_path_get_basename (filename);
diff --git a/src/common/dbus/example.c b/src/common/dbus/example.c
index c3ad4ff3..0228b884 100644
--- a/src/common/dbus/example.c
+++ b/src/common/dbus/example.c
@@ -33,7 +33,7 @@ guint command_id;
 guint server_id;
 
 static void
-write_error (char *message,
+write_error (const char *message,
 	     GError **error)
 {
 	if (error == NULL || *error == NULL) {
diff --git a/src/common/dcc.c b/src/common/dcc.c
index 169a0f76..881bcf78 100644
--- a/src/common/dcc.c
+++ b/src/common/dcc.c
@@ -23,8 +23,9 @@
  * Jim Seymour (jseymour@LinxNet.com)
  */
 
-/* we only use 32 bits, but without this define, you get only 31! */
+/* Required to make lseek use off64_t, but doesn't work on Windows */
 #define _FILE_OFFSET_BITS 64
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -57,13 +58,9 @@
 #include "url.h"
 #include "hexchatc.h"
 
-#ifdef USE_DCC64
-#define BIG_STR_TO_INT(x) strtoull(x,NULL,10)
+/* Setting _FILE_OFFSET_BITS to 64 doesn't change lseek to use off64_t on Windows, so override lseek to the version that does */
 #ifdef WIN32
-#define stat _stat64
-#endif
-#else
-#define BIG_STR_TO_INT(x) strtoul(x,NULL,10)
+#define lseek _lseeki64
 #endif
 
 static char *dcctypes[] = { "SEND", "RECV", "CHAT", "CHAT" };
@@ -78,7 +75,7 @@ struct dccstat_info dccstat[] = {
 };
 
 static int dcc_global_throttle;	/* 0x1 = sends, 0x2 = gets */
-/*static*/ int dcc_sendcpssum, dcc_getcpssum;
+static gint64 dcc_sendcpssum, dcc_getcpssum;
 
 static struct DCC *new_dcc (void);
 static void dcc_close (struct DCC *dcc, int dccstat, int destroy);
@@ -127,11 +124,12 @@ static void
 dcc_calc_cps (struct DCC *dcc)
 {
 	GTimeVal now;
-	int oldcps;
+	gint64 oldcps;
 	double timediff, startdiff;
 	int glob_throttle_bit, wasthrottled;
-	int *cpssum, glob_limit;
-	DCC_SIZE pos, posdiff;
+	gint64 *cpssum;
+	int glob_limit;
+	goffset pos, posdiff;
 
 	g_get_current_time (&now);
 
@@ -169,8 +167,7 @@ dcc_calc_cps (struct DCC *dcc)
 
 		posdiff = pos - dcc->lastcpspos;
 		oldcps = dcc->cps;
-		dcc->cps = ((double) posdiff / timediff) * (timediff / startdiff) +
-			(double) dcc->cps * (1.0 - (timediff / startdiff));
+		dcc->cps = (gint64) ((posdiff / timediff) * (timediff / startdiff) + dcc->cps * (1.0 - (timediff / startdiff)));
 
 		*cpssum += dcc->cps - oldcps;
 	}
@@ -312,7 +309,7 @@ dcc_lookup_proxy (char *host, struct sockaddr_in *addr)
 			memcpy (&addr->sin_addr, &cache_addr, 4);
 			return TRUE;
 		}
-		free (cache_host);
+		g_free (cache_host);
 		cache_host = NULL;
 	}
 
@@ -321,7 +318,7 @@ dcc_lookup_proxy (char *host, struct sockaddr_in *addr)
 	{
 		memcpy (&addr->sin_addr, h->h_addr, 4);
 		memcpy (&cache_addr, h->h_addr, 4);
-		cache_host = strdup (host);
+		cache_host = g_strdup (host);
 		/* cppcheck-suppress memleak */
 		return TRUE;
 	}
@@ -409,7 +406,7 @@ dcc_close (struct DCC *dcc, int dccstat, int destroy)
 	dcc->dccstat = dccstat;
 	if (dcc->dccchat)
 	{
-		free (dcc->dccchat);
+		g_free (dcc->dccchat);
 		dcc->dccchat = NULL;
 	}
 
@@ -417,14 +414,11 @@ dcc_close (struct DCC *dcc, int dccstat, int destroy)
 	{
 		dcc_list = g_slist_remove (dcc_list, dcc);
 		fe_dcc_remove (dcc);
-		if (dcc->proxy)
-			free (dcc->proxy);
-		if (dcc->file)
-			free (dcc->file);
-		if (dcc->destfile)
-			g_free (dcc->destfile);
-		free (dcc->nick);
-		free (dcc);
+		g_free (dcc->proxy);
+		g_free (dcc->file);
+		g_free (dcc->destfile);
+		g_free (dcc->nick);
+		g_free (dcc);
 		return;
 	}
 
@@ -493,14 +487,13 @@ dcc_write_chat (char *nick, char *text)
 	if (dcc && dcc->dccstat == STAT_ACTIVE)
 	{
 		len = strlen (text);
-		tcp_send_real (NULL, dcc->sok, dcc->serv->encoding, dcc->serv->using_irc,
-							text, len);
+		tcp_send_real (NULL, dcc->sok, dcc->serv->write_converter, text, len);
 		send (dcc->sok, "\n", 1, 0);
 		dcc->size += len;
 		fe_dcc_update (dcc);
 		return dcc;
 	}
-	return 0;
+	return NULL;
 }
 
 /* returns: 0 - ok
@@ -512,36 +505,11 @@ dcc_chat_line (struct DCC *dcc, char *line)
 	session *sess;
 	char *word[PDIWORDS];
 	char *po;
-	char *utf;
-	char *conv;
 	int ret, i;
-	int len;
-	gsize utf_len;
 	char portbuf[32];
 	message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT;
 
-	len = strlen (line);
-	if (dcc->serv->using_cp1255)
-		len++;	/* include the NUL terminator */
-
-	if (dcc->serv->using_irc) /* using "IRC" encoding (CP1252/UTF-8 hybrid) */
-		utf = NULL;
-	else if (dcc->serv->encoding == NULL)     /* system */
-		utf = g_locale_to_utf8 (line, len, NULL, &utf_len, NULL);
-	else
-		utf = g_convert (line, len, "UTF-8", dcc->serv->encoding, 0, &utf_len, 0);
-
-	if (utf)
-	{
-		line = utf;
-		len = utf_len;
-	}
-
-	if (dcc->serv->using_cp1255 && len > 0)
-		len--;
-
-	/* we really need valid UTF-8 now */
-	conv = text_validate (&line, &len);
+	line = text_convert_invalid (line, -1, dcc->serv->read_converter, unicode_fallback_string, NULL);
 
 	sess = find_dialog (dcc->serv, dcc->nick);
 	if (!sess)
@@ -562,24 +530,18 @@ dcc_chat_line (struct DCC *dcc, char *line)
 	/* did the plugin close it? */
 	if (!g_slist_find (dcc_list, dcc))
 	{
-		if (utf)
-			g_free (utf);
-		if (conv)
-			g_free (conv);
+		g_free (line);
 		return 1;
 	}
 
 	/* did the plugin eat the event? */
 	if (ret)
 	{
-		if (utf)
-			g_free (utf);
-		if (conv)
-			g_free (conv);
+		g_free (line);
 		return 0;
 	}
 
-	url_check_line (line, len);
+	url_check_line (line);
 
 	if (line[0] == 1 && !g_ascii_strncasecmp (line + 1, "ACTION", 6))
 	{
@@ -592,10 +554,7 @@ dcc_chat_line (struct DCC *dcc, char *line)
 	{
 		inbound_privmsg (dcc->serv, dcc->nick, "", line, FALSE, &no_tags);
 	}
-	if (utf)
-		g_free (utf);
-	if (conv)
-		g_free (conv);
+	g_free (line);
 	return 0;
 }
 
@@ -700,20 +659,26 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 
 		if (dcc->resumable)
 		{
-			dcc->fp = g_open (dcc->destfile, O_WRONLY | O_APPEND | OFLAGS, 0);
+			gchar *filename_fs = g_filename_from_utf8(dcc->destfile, -1, NULL, NULL, NULL);
+			dcc->fp = g_open(dcc->destfile, O_WRONLY | O_APPEND | OFLAGS, 0);
+			g_free (filename_fs);
+
 			dcc->pos = dcc->resumable;
 			dcc->ack = dcc->resumable;
-		} else
+		}
+		else
 		{
+			gchar *filename_fs;
+
 			if (g_access (dcc->destfile, F_OK) == 0)
 			{
 				n = 0;
 				do
 				{
 					n++;
-					snprintf (buf, sizeof (buf), "%s.%d", dcc->destfile, n);
+					g_snprintf (buf, sizeof (buf), "%s.%d", dcc->destfile, n);
 				}
-				while (access (buf, F_OK) == 0);
+				while (g_access (buf, F_OK) == 0);
 
 				old = dcc->destfile;
 				dcc->destfile = g_strdup (buf);
@@ -722,9 +687,10 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 								 old, dcc->destfile, NULL, NULL, 0);
 				g_free (old);
 			}
-			dcc->fp =
-				g_open (dcc->destfile, OFLAGS | O_TRUNC | O_WRONLY | O_CREAT,
-						prefs.hex_dcc_permissions);
+
+			filename_fs = g_filename_from_utf8 (dcc->destfile, -1, NULL, NULL, NULL);
+			dcc->fp = g_open (filename_fs, OFLAGS | O_TRUNC | O_WRONLY | O_CREAT, prefs.hex_dcc_permissions);
+			g_free (filename_fs);
 		}
 	}
 	if (dcc->fp == -1)
@@ -792,7 +758,7 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 			dcc_close (dcc, STAT_DONE, FALSE);
 			dcc_calc_average_cps (dcc);	/* this must be done _after_ dcc_close, or dcc_remove_from_sum will see the wrong value in dcc->cps */
 			/* cppcheck-suppress deallocuse */
-			sprintf (buf, "%d", dcc->cps);
+			sprintf (buf, "%" G_GINT64_FORMAT, dcc->cps);
 			EMIT_SIGNAL (XP_TE_DCCRECVCOMP, dcc->serv->front_session,
 							 dcc->file, dcc->destfile, dcc->nick, buf, 0);
 			return TRUE;
@@ -870,7 +836,7 @@ dcc_connect_finished (GIOChannel *source, GIOCondition condition, struct DCC *dc
 		return TRUE;
 
 	dcc->dccstat = STAT_ACTIVE;
-	snprintf (host, sizeof host, "%s:%d", net_ip (dcc->addr), dcc->port);
+	g_snprintf (host, sizeof host, "%s:%d", net_ip (dcc->addr), dcc->port);
 
 	switch (dcc->type)
 	{
@@ -893,8 +859,7 @@ dcc_connect_finished (GIOChannel *source, GIOCondition condition, struct DCC *dc
 		dcc_open_query (dcc->serv, dcc->nick);
 	case TYPE_CHATRECV:	/* normal chat */
 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read_chat, dcc);
-		dcc->dccchat = malloc (sizeof (struct dcc_chat));
-		dcc->dccchat->pos = 0;
+		dcc->dccchat = g_new0 (struct dcc_chat, 1);
 		EMIT_SIGNAL (XP_TE_DCCCONCHAT, dcc->serv->front_session,
 						 dcc->nick, host, NULL, NULL, 0);
 		break;
@@ -990,7 +955,7 @@ dcc_wingate_proxy_traverse (GIOChannel *source, GIOCondition condition, struct D
 	struct proxy_state *proxy = dcc->proxy;
 	if (proxy->phase == 0)
 	{
-		proxy->buffersize = snprintf ((char*) proxy->buffer, MAX_PROXY_BUFFER,
+		proxy->buffersize = g_snprintf ((char*) proxy->buffer, MAX_PROXY_BUFFER,
 										"%s %d\r\n", net_ip(dcc->addr),
 										dcc->port);
 		proxy->bufferused = 0;
@@ -1288,16 +1253,16 @@ dcc_http_proxy_traverse (GIOChannel *source, GIOCondition condition, struct DCC
 		char auth_data2[68];
 		int n, n2;
 
-		n = snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
+		n = g_snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
                                           net_ip(dcc->addr), dcc->port);
 		if (prefs.hex_net_proxy_auth)
 		{
-			n2 = snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
+			n2 = g_snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
 							prefs.hex_net_proxy_user, prefs.hex_net_proxy_pass);
 			base64_encode (auth_data, auth_data2, n2);
-			n += snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
+			n += g_snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
 		}
-		n += snprintf (buf+n, sizeof (buf)-n, "\r\n");
+		n += g_snprintf (buf+n, sizeof (buf)-n, "\r\n");
 		proxy->buffersize = n;
 		proxy->bufferused = 0;
 		memcpy (proxy->buffer, buf, proxy->buffersize);
@@ -1373,14 +1338,7 @@ dcc_proxy_connect (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 	if (!dcc_did_connect (source, condition, dcc))
 		return TRUE;
 
-	dcc->proxy = malloc (sizeof (struct proxy_state));
-	if (!dcc->proxy)
-	{
-		dcc->dccstat = STAT_FAILED;
-		fe_dcc_update (dcc);
-		return TRUE;
-	}
-	memset (dcc->proxy, 0, sizeof (struct proxy_state));
+	dcc->proxy = g_new0 (struct proxy_state, 1);
 
 	switch (prefs.hex_net_proxy_type)
 	{
@@ -1415,12 +1373,12 @@ dcc_connect (struct DCC *dcc)
 		}
 		/* possible problems with filenames containing spaces? */
 		if (dcc->type == TYPE_RECV)
-			snprintf (tbuf, sizeof (tbuf), strchr (dcc->file, ' ') ?
-					"DCC SEND \"%s\" %u %d %"DCC_SFMT" %d" :
-					"DCC SEND %s %u %d %"DCC_SFMT" %d", dcc->file,
+			g_snprintf (tbuf, sizeof (tbuf), strchr (dcc->file, ' ') ?
+					"DCC SEND \"%s\" %u %d %" G_GUINT64_FORMAT " %d" :
+					"DCC SEND %s %u %d %" G_GUINT64_FORMAT " %d", dcc->file,
 					dcc->addr, dcc->port, dcc->size, dcc->pasvid);
 		else
-			snprintf (tbuf, sizeof (tbuf), "DCC CHAT chat %u %d %d",
+			g_snprintf (tbuf, sizeof (tbuf), "DCC CHAT chat %u %d %d",
 				dcc->addr, dcc->port, dcc->pasvid);
 		dcc->serv->p_ctcp (dcc->serv, dcc->nick, tbuf);
 	}
@@ -1463,15 +1421,13 @@ dcc_send_data (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 
 	if (!dcc->fastsend)
 	{
-		if (dcc->ack < dcc->pos)
+		if (dcc->ack < (dcc->pos & 0xFFFFFFFF))
 			return TRUE;
 	}
 	else if (!dcc->wiotag)
 		dcc->wiotag = fe_input_add (sok, FIA_WRITE, dcc_send_data, dcc);
 
-	buf = malloc (prefs.hex_dcc_blocksize);
-	if (!buf)
-		return TRUE;
+	buf = g_malloc (prefs.hex_dcc_blocksize);
 
 	lseek (dcc->fp, dcc->pos, SEEK_SET);
 	len = read (dcc->fp, buf, prefs.hex_dcc_blocksize);
@@ -1482,7 +1438,7 @@ dcc_send_data (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 	if (sent < 0 && !(would_block ()))
 	{
 abortit:
-		free (buf);
+		g_free (buf);
 		EMIT_SIGNAL (XP_TE_DCCSENDFAIL, dcc->serv->front_session,
 						 file_part (dcc->file), dcc->nick,
 						 errorstring (sock_error ()), NULL, 0);
@@ -1506,7 +1462,7 @@ abortit:
 		}
 	}
 
-	free (buf);
+	g_free (buf);
 
 	return TRUE;
 }
@@ -1538,7 +1494,7 @@ dcc_handle_new_ack (struct DCC *dcc)
 		dcc_close (dcc, STAT_DONE, FALSE);
 		dcc_calc_average_cps (dcc);	/* this must be done _after_ dcc_close, or dcc_remove_from_sum will see the wrong value in dcc->cps */
 		/* cppcheck-suppress deallocuse */
-		sprintf (buf, "%d", dcc->cps);
+		sprintf (buf, "%" G_GINT64_FORMAT, dcc->cps);
 		EMIT_SIGNAL (XP_TE_DCCSENDCOMP, dcc->serv->front_session,
 						 file_part (dcc->file), dcc->nick, buf, NULL, 0);
 		done = TRUE;
@@ -1548,12 +1504,10 @@ dcc_handle_new_ack (struct DCC *dcc)
 		dcc_send_data (NULL, 0, (gpointer)dcc);
 	}
 
-#ifdef USE_DCC64
 	/* take the top 32 of "bytes send" and bottom 32 of "ack" */
 	dcc->ack = (dcc->pos & G_GINT64_CONSTANT (0xffffffff00000000)) |
 					(dcc->ack & 0xffffffff);
 	/* dcc->ack is only used for CPS and PERCENTAGE calcs from now on... */
-#endif
 
 	return done;
 }
@@ -1622,7 +1576,7 @@ dcc_accept (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 	dcc->lasttime = dcc->starttime = time (0);
 	dcc->fastsend = prefs.hex_dcc_fast_send;
 
-	snprintf (host, sizeof (host), "%s:%d", net_ip (dcc->addr), dcc->port);
+	g_snprintf (host, sizeof (host), "%s:%d", net_ip (dcc->addr), dcc->port);
 
 	switch (dcc->type)
 	{
@@ -1638,8 +1592,7 @@ dcc_accept (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 	case TYPE_CHATSEND:
 		dcc_open_query (dcc->serv, dcc->nick);
 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read_chat, dcc);
-		dcc->dccchat = malloc (sizeof (struct dcc_chat));
-		dcc->dccchat->pos = 0;
+		dcc->dccchat = g_new0 (struct dcc_chat, 1);
 		EMIT_SIGNAL (XP_TE_DCCCONCHAT, dcc->serv->front_session,
 						 dcc->nick, host, NULL, NULL, 0);
 		break;
@@ -1762,7 +1715,7 @@ dcc_listen_init (struct DCC *dcc, session *sess)
 
 static struct session *dccsess;
 static char *dccto;				  /* lame!! */
-static int dccmaxcps;
+static gint64 dccmaxcps;
 static int recursive = FALSE;
 
 static void
@@ -1772,21 +1725,25 @@ dcc_send_wild (char *file)
 }
 
 void
-dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
+dcc_send (struct session *sess, char *to, char *filename, gint64 maxcps, int passive)
 {
 	char outbuf[512];
-	GStatBuf st;
+	GFileInfo *file_info;
+	GFile *file;
 	struct DCC *dcc;
+	gchar *filename_fs;
+	GFileType file_type;
+	goffset file_size;
 
-	file = expand_homedir (file);
+	filename = expand_homedir (filename);
 
-	if (!recursive && (strchr (file, '*') || strchr (file, '?')))
+	if (!recursive && (strchr (filename, '*') || strchr (filename, '?')))
 	{
 		char path[256];
 		char wild[256];
 
-		safe_strcpy (wild, file_part (file), sizeof (wild));
-		path_part (file, path, sizeof (path));
+		safe_strcpy (wild, file_part (filename), sizeof (wild));
+		path_part (filename, path, sizeof (path));
 		if (path[0] != '/' || path[1] != '\0')
 			path[strlen (path) - 1] = 0;	/* remove trailing slash */
 
@@ -1794,7 +1751,7 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 		dccto = to;
 		dccmaxcps = maxcps;
 
-		free (file);
+		g_free (filename);
 
 		recursive = TRUE;
 		for_files (path, wild, dcc_send_wild);
@@ -1806,91 +1763,135 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 	dcc = new_dcc ();
 	if (!dcc)
 	{
-		free (file);
+		g_free (filename);
 		return;
 	}
-	dcc->file = file;
+
+	dcc->file = filename;
 	dcc->maxcps = maxcps;
 
-	if (g_stat (file, &st) != -1)
+	filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
+	if (filename_fs == NULL)
 	{
+		PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
+		PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
 
-#ifndef USE_DCC64
-		if (sizeof (st.st_size) > 4 && st.st_size > 4294967295U)
-		{
-			PrintText (sess, "Cannot send files larger than 4 GB.\n");
-			goto xit;
-		}
-#endif
+		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
 
-		if (!(*file_part (file)) || S_ISDIR (st.st_mode) || st.st_size < 1)
-		{
-			PrintText (sess, "Cannot send directories or empty files.\n");
-			goto xit;
-		}
+		return;
+	}
 
-		dcc->starttime = dcc->offertime = time (0);
-		dcc->serv = sess->server;
-		dcc->dccstat = STAT_QUEUED;
-		dcc->size = st.st_size;
-		dcc->type = TYPE_SEND;
-		dcc->fp = g_open (file, OFLAGS | O_RDONLY, 0);
-		if (dcc->fp != -1)
-		{
-			if (passive || dcc_listen_init (dcc, sess))
-			{
-				char havespaces = 0;
-				while (*file)
-				{
-					if (*file == ' ')
-					{
-						if (prefs.hex_dcc_send_fillspaces)
-				    		*file = '_';
-					  	else
-					   	havespaces = 1;
-					}
-					file++;
-				}
-				dcc->nick = strdup (to);
-				if (prefs.hex_gui_autoopen_send)
-				{
-					if (fe_dcc_open_send_win (TRUE))	/* already open? add */
-						fe_dcc_add (dcc);
-				} else
-					fe_dcc_add (dcc);
+	file = g_file_new_for_path (filename_fs);
+	if (file == NULL)
+	{
+		PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
+		PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
 
-				if (passive)
-				{
-					dcc->pasvid = new_id();
-					snprintf (outbuf, sizeof (outbuf), (havespaces) ?
-							"DCC SEND \"%s\" 199 0 %" DCC_SFMT " %d" :
-							"DCC SEND %s 199 0 %" DCC_SFMT " %d",
-							file_part (dcc->file),
-							dcc->size, dcc->pasvid);
-				}
-				else
-				{
-					snprintf (outbuf, sizeof (outbuf), (havespaces) ?
-							"DCC SEND \"%s\" %u %d %"DCC_SFMT :
-							"DCC SEND %s %u %d %"DCC_SFMT,
-							file_part (dcc->file), dcc->addr,
-							dcc->port, dcc->size);
-				}
-				sess->server->p_ctcp (sess->server, to, outbuf);
+		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
 
-				EMIT_SIGNAL (XP_TE_DCCOFFER, sess, file_part (dcc->file),
-								 to, dcc->file, NULL, 0);
-			} else
+		g_free (filename_fs);
+
+		return;
+	}
+
+	file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+
+	g_object_unref (file);
+
+	if (file_info == NULL)
+	{
+		PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
+		PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
+
+		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
+
+		g_free (filename_fs);
+
+		return;
+	}
+
+	file_type = g_file_info_get_file_type (file_info);
+	file_size = g_file_info_get_size (file_info);
+
+	g_object_unref (file_info);
+
+	if (*file_part (filename) == '\0' || file_type == G_FILE_TYPE_DIRECTORY || file_size <= 0)
+	{
+		PrintText (sess, "Cannot send directories or empty files.\n");
+
+		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
+
+		g_free (filename_fs);
+
+		return;
+	}
+
+	dcc->starttime = dcc->offertime = time (0);
+	dcc->serv = sess->server;
+	dcc->dccstat = STAT_QUEUED;
+	dcc->size = file_size;
+	dcc->type = TYPE_SEND;
+	dcc->fp = g_open (filename_fs, OFLAGS | O_RDONLY, 0);
+
+	g_free (filename_fs);
+
+	if (dcc->fp == -1)
+	{
+		PrintText (sess, "Cannot send directories or empty files.\n");
+
+		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
+
+		return;
+	}
+
+	if (passive || dcc_listen_init (dcc, sess))
+	{
+		char havespaces = 0;
+		while (*filename)
+		{
+			if (*filename == ' ')
 			{
-				dcc_close (dcc, 0, TRUE);
+				if (prefs.hex_dcc_send_fillspaces)
+				    *filename = '_';
+				else
+				havespaces = 1;
 			}
-			return;
+			filename++;
 		}
+		dcc->nick = g_strdup (to);
+		if (prefs.hex_gui_autoopen_send)
+		{
+			if (fe_dcc_open_send_win (TRUE))	/* already open? add */
+				fe_dcc_add (dcc);
+		} else
+			fe_dcc_add (dcc);
+
+		if (passive)
+		{
+			dcc->pasvid = new_id();
+			g_snprintf (outbuf, sizeof (outbuf), (havespaces) ?
+					"DCC SEND \"%s\" 199 0 %" G_GUINT64_FORMAT " %d" :
+					"DCC SEND %s 199 0 %" G_GUINT64_FORMAT " %d",
+					file_part (dcc->file),
+					dcc->size, dcc->pasvid);
+		}
+		else
+		{
+			g_snprintf (outbuf, sizeof (outbuf), (havespaces) ?
+					"DCC SEND \"%s\" %u %d %" G_GUINT64_FORMAT :
+					"DCC SEND %s %u %d %" G_GUINT64_FORMAT,
+					file_part (dcc->file), dcc->addr,
+					dcc->port, dcc->size);
+		}
+		sess->server->p_ctcp (sess->server, to, outbuf);
+
+		EMIT_SIGNAL (XP_TE_DCCOFFER, sess, file_part (dcc->file),
+							to, dcc->file, NULL, 0);
+	}
+	else
+	{
+		dcc_close (dcc, 0, TRUE);
 	}
-	PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
-	PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
-xit:
-	dcc_close (dcc, 0, TRUE);		/* dcc_close will free dcc->file */
 }
 
 static struct DCC *
@@ -1906,7 +1907,7 @@ find_dcc_from_id (int id, int type)
 		return dcc;
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 static struct DCC *
@@ -1922,7 +1923,7 @@ find_dcc_from_port (int port, int type)
 			return dcc;
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 struct DCC *
@@ -1947,7 +1948,7 @@ find_dcc (char *nick, char *file, int type)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 /* called when we receive a NICK change from server */
@@ -1965,9 +1966,8 @@ dcc_change_nick (struct server *serv, char *oldnick, char *newnick)
 		{
 			if (!serv->p_cmp (dcc->nick, oldnick))
 			{
-				if (dcc->nick)
-					free (dcc->nick);
-				dcc->nick = strdup (newnick);
+				g_free (dcc->nick);
+				dcc->nick = g_strdup (newnick);
 			}
 		}
 		list = list->next;
@@ -1976,68 +1976,153 @@ dcc_change_nick (struct server *serv, char *oldnick, char *newnick)
 
 /* is the destination file the same? new_dcc is not opened yet */
 
-static int
+static gboolean
 is_same_file (struct DCC *dcc, struct DCC *new_dcc)
 {
-#ifndef WIN32
-	GStatBuf st_a, st_b;
-#endif
+	gboolean result = FALSE;
+	gchar *filename_fs = NULL, *new_filename_fs = NULL;
+	GFile *file = NULL, *new_file = NULL;
+	GFileInfo *file_info = NULL, *new_file_info = NULL;
+	char *file_id = NULL, *new_file_id = NULL;
+	char *filesystem_id = NULL, *new_filesystem_id = NULL;
 
 	/* if it's the same filename, must be same */
 	if (strcmp (dcc->destfile, new_dcc->destfile) == 0)
+	{
 		return TRUE;
+	}
 
-	/* now handle case-insensitive Filesystems: HFS+, FAT */
-#ifdef WIN32
-	/* warning no win32 implementation - behaviour may be unreliable */
-#else
-	/* this fstat() shouldn't really fail */
-	if ((dcc->fp == -1 ? g_stat (dcc->destfile, &st_a) : fstat (dcc->fp, &st_a)) == -1)
-		return FALSE;
-	if (g_stat (new_dcc->destfile, &st_b) == -1)
-		return FALSE;
+	filename_fs = g_filename_from_utf8 (dcc->file, -1, NULL, NULL, NULL);
+	if (filename_fs == NULL)
+	{
+		goto exit;
+	}
 
-	/* same inode, same device, same file! */
-	if (st_a.st_ino == st_b.st_ino &&
-		 st_a.st_dev == st_b.st_dev)
-		return TRUE;
-#endif
+	new_filename_fs = g_filename_from_utf8 (new_dcc->file, -1, NULL, NULL, NULL);
+	if (new_filename_fs == NULL)
+	{
+		goto exit;
+	}
 
-	return FALSE;
+	file = g_file_new_for_path (filename_fs);
+	if (file == NULL)
+	{
+		goto exit;
+	}
+
+	new_file = g_file_new_for_path (new_filename_fs);
+	if (new_file == NULL)
+	{
+		goto exit;
+	}
+
+	file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_ID_FILE "," G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+	if (file_info == NULL)
+	{
+		goto exit;
+	}
+
+	new_file_info = g_file_query_info (new_file, G_FILE_ATTRIBUTE_ID_FILE "," G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+	if (new_file_info == NULL)
+	{
+		goto exit;
+	}
+
+	file_id = g_file_info_get_attribute_as_string (file_info, G_FILE_ATTRIBUTE_ID_FILE);
+	new_file_id = g_file_info_get_attribute_as_string (new_file_info, G_FILE_ATTRIBUTE_ID_FILE);
+
+	filesystem_id = g_file_info_get_attribute_as_string (file_info, G_FILE_ATTRIBUTE_ID_FILE);
+	new_filesystem_id = g_file_info_get_attribute_as_string (new_file_info, G_FILE_ATTRIBUTE_ID_FILE);
+
+	if (file_id != NULL && new_file_id != NULL && filesystem_id != NULL && new_filesystem_id != NULL && strcmp (file_id, new_file_id) == 0 && strcmp (filesystem_id, new_filesystem_id) == 0)
+	{
+		result = TRUE;
+	}
+
+exit:
+	g_free (filename_fs);
+	g_free (new_filename_fs);
+
+	if (file != NULL)
+	{
+		g_object_unref (file);
+	}
+
+	if (new_file != NULL)
+	{
+		g_object_unref (new_file);
+	}
+
+	if (file_info != NULL)
+	{
+		g_object_unref (file_info);
+	}
+
+	if (new_file_info != NULL)
+	{
+		g_object_unref (new_file_info);
+	}
+
+	g_free (file_id);
+	g_free (new_file_id);
+	g_free(filesystem_id);
+	g_free(new_filesystem_id);
+
+	return result;
 }
 
-static int
-is_resumable (struct DCC *dcc)
+static void
+update_is_resumable (struct DCC *dcc)
 {
+	gchar *filename_fs = g_filename_from_utf8 (dcc->destfile, -1, NULL, NULL, NULL);
+
 	dcc->resumable = 0;
 
 	/* Check the file size */
-	if (g_access (dcc->destfile, W_OK) == 0)
+	if (filename_fs != NULL && g_access(filename_fs, W_OK) == 0)
 	{
-		GStatBuf st;
-
-		if (g_stat (dcc->destfile, &st) != -1)
+		GFile *file = g_file_new_for_path (filename_fs);
+		if (file != NULL)
 		{
-			if (st.st_size < dcc->size)
+			GFileInfo *file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+
+			if (file_info != NULL)
 			{
-				dcc->resumable = st.st_size;
-				dcc->pos = st.st_size;
+				goffset file_size_offset = g_file_info_get_size (file_info);
+				guint64 file_size = (file_size_offset >= 0) ? (guint64) file_size_offset : 0;
+				if (file_size < dcc->size)
+				{
+					dcc->resumable = file_size;
+					dcc->pos = file_size;
+				}
+				else
+				{
+					dcc->resume_error = 2;
+				}
+
+				g_object_unref (file_info);
 			}
 			else
-				dcc->resume_error = 2;
-		} else
+			{
+				dcc->resume_errno = errno;
+				dcc->resume_error = 1;
+			}
+
+			g_object_unref(file);
+		}
+		else
 		{
 			dcc->resume_errno = errno;
 			dcc->resume_error = 1;
 		}
-	} else
+	}
+	else
 	{
 		dcc->resume_errno = errno;
 		dcc->resume_error = 1;
 	}
 
 	/* Now verify that this DCC is not already in progress from someone else */
-
 	if (dcc->resumable)
 	{
 		GSList *list = dcc_list;
@@ -2059,8 +2144,6 @@ is_resumable (struct DCC *dcc)
 			list = list->next;
 		}
 	}
-
-	return dcc->resumable;
 }
 
 void
@@ -2100,7 +2183,7 @@ dcc_get_with_destfile (struct DCC *dcc, char *file)
 	dcc->destfile = g_strdup (file);	/* utf-8 */
 
 	/* since destfile changed, must check resumability again */
-	is_resumable (dcc);
+	update_is_resumable (dcc);
 
 	dcc_get (dcc);
 }
@@ -2133,14 +2216,11 @@ dcc_get_nick (struct session *sess, char *nick)
 static struct DCC *
 new_dcc (void)
 {
-	struct DCC *dcc = malloc (sizeof (struct DCC));
-	if (!dcc)
-		return 0;
-	memset (dcc, 0, sizeof (struct DCC));
+	struct DCC *dcc = g_new0 (struct DCC, 1);
 	dcc->sok = -1;
 	dcc->fp = -1;
 	dcc_list = g_slist_prepend (dcc_list, dcc);
-	return (dcc);
+	return dcc;
 }
 
 void
@@ -2187,7 +2267,7 @@ dcc_chat (struct session *sess, char *nick, int passive)
 	dcc->serv = sess->server;
 	dcc->dccstat = STAT_QUEUED;
 	dcc->type = TYPE_CHATSEND;
-	dcc->nick = strdup (nick);
+	dcc->nick = g_strdup (nick);
 	if (passive || dcc_listen_init (dcc, sess))
 	{
 		if (prefs.hex_gui_autoopen_chat)
@@ -2200,11 +2280,11 @@ dcc_chat (struct session *sess, char *nick, int passive)
 		if (passive)
 		{
 			dcc->pasvid = new_id ();
-			snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat 199 %d %d",
+			g_snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat 199 %d %d",
 						 dcc->port, dcc->pasvid);
 		} else
 		{
-			snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat %u %d",
+			g_snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat %u %d",
 						 dcc->addr, dcc->port);
 		}
 		dcc->serv->p_ctcp (dcc->serv, nick, outbuf);
@@ -2230,9 +2310,9 @@ dcc_resume (struct DCC *dcc)
 	{
 		dcc->resume_sent = 1;
 		/* filename contains spaces? Quote them! */
-		snprintf (tbuf, sizeof (tbuf) - 10, strchr (dcc->file, ' ') ?
-					  "DCC RESUME \"%s\" %d %"DCC_SFMT :
-					  "DCC RESUME %s %d %"DCC_SFMT,
+		g_snprintf (tbuf, sizeof (tbuf) - 10, strchr (dcc->file, ' ') ?
+					  "DCC RESUME \"%s\" %d %" G_GUINT64_FORMAT :
+					  "DCC RESUME %s %d %" G_GUINT64_FORMAT,
 					  dcc->file, dcc->port, dcc->resumable);
 
 		if (dcc->pasvid)
@@ -2287,7 +2367,7 @@ dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid)
 		dcc->addr = addr;
 		dcc->port = port;
 		dcc->pasvid = pasvid;
-		dcc->nick = strdup (nick);
+		dcc->nick = g_strdup (nick);
 		dcc->starttime = time (0);
 
 		EMIT_SIGNAL (XP_TE_DCCCHATOFFER, sess->server->front_session, nick,
@@ -2307,7 +2387,7 @@ dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid)
 		else
 		{
 			char buff[128];
-			snprintf (buff, sizeof (buff), "%s is offering DCC Chat. Do you want to accept?", nick);
+			g_snprintf (buff, sizeof (buff), "%s is offering DCC Chat. Do you want to accept?", nick);
 			fe_confirm (buff, dcc_confirm_chat, dcc_deny_chat, dcc);
 		}
 	}
@@ -2316,7 +2396,7 @@ dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid)
 }
 
 static struct DCC *
-dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, guint32 addr, int pasvid)
+dcc_add_file (session *sess, char *file, guint64 size, int port, char *nick, guint32 addr, int pasvid)
 {
 	struct DCC *dcc;
 	char tbuf[512];
@@ -2324,7 +2404,7 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu
 	dcc = new_dcc ();
 	if (dcc)
 	{
-		dcc->file = strdup (file);
+		dcc->file = g_strdup (file);
 
 		dcc->destfile = g_malloc (strlen (prefs.hex_dcc_dir) + strlen (nick) +
 										  strlen (file) + 4);
@@ -2359,14 +2439,14 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu
 		dcc->port = port;
 		dcc->pasvid = pasvid;
 		dcc->size = size;
-		dcc->nick = strdup (nick);
+		dcc->nick = g_strdup (nick);
 		dcc->maxcps = prefs.hex_dcc_max_get_cps;
 
-		is_resumable (dcc);
+		update_is_resumable (dcc);
 
 		if (prefs.hex_dcc_auto_recv == 1)
 		{
-			snprintf (tbuf, sizeof (tbuf), _("%s is offering \"%s\". Do you want to accept?"), nick, file);
+			g_snprintf (tbuf, sizeof (tbuf), _("%s is offering \"%s\". Do you want to accept?"), nick, file);
 			fe_confirm (tbuf, dcc_confirm_send, dcc_deny_send, dcc);
 		}
 		else if (prefs.hex_dcc_auto_recv == 2)
@@ -2380,8 +2460,8 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu
 		} else
 			fe_dcc_add (dcc);
 	}
-	sprintf (tbuf, "%"DCC_SFMT, size);
-	snprintf (tbuf + 24, 300, "%s:%d", net_ip (addr), port);
+	sprintf (tbuf, "%" G_GUINT64_FORMAT, size);
+	g_snprintf (tbuf + 24, 300, "%s:%d", net_ip (addr), port);
 	EMIT_SIGNAL (XP_TE_DCCSENDOFFER, sess->server->front_session, nick,
 					 file, tbuf, tbuf + 24, 0);
 
@@ -2397,7 +2477,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 	char *type = word[5];
 	int port, pasvid = 0;
 	guint32 addr;
-	DCC_SIZE size;
+	guint64 size;
 	int psend = 0;
 
 	if (!g_ascii_strcasecmp (type, "CHAT"))
@@ -2463,7 +2543,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 			dcc = find_dcc (nick, word[6], TYPE_SEND);
 		if (dcc)
 		{
-			size = BIG_STR_TO_INT (word[8]);
+			size = g_ascii_strtoull (word[8], NULL, 10);
 			dcc->resumable = size;
 			if (dcc->resumable < dcc->size)
 			{
@@ -2473,19 +2553,19 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 
 				/* Checking if dcc is passive and if filename contains spaces */
 				if (dcc->pasvid)
-					snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
-							"DCC ACCEPT \"%s\" %d %"DCC_SFMT" %d" :
-							"DCC ACCEPT %s %d %"DCC_SFMT" %d",
+					g_snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
+							"DCC ACCEPT \"%s\" %d %" G_GUINT64_FORMAT " %d" :
+							"DCC ACCEPT %s %d %" G_GUINT64_FORMAT " %d",
 							file_part (dcc->file), port, dcc->resumable, dcc->pasvid);
 				else
-					snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
-							"DCC ACCEPT \"%s\" %d %"DCC_SFMT :
-							"DCC ACCEPT %s %d %"DCC_SFMT,
+					g_snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
+							"DCC ACCEPT \"%s\" %d %" G_GUINT64_FORMAT :
+							"DCC ACCEPT %s %d %" G_GUINT64_FORMAT,
 							file_part (dcc->file), port, dcc->resumable);
 
 				dcc->serv->p_ctcp (dcc->serv, dcc->nick, tbuf);
 			}
-			sprintf (tbuf, "%"DCC_SFMT, dcc->pos);
+			sprintf (tbuf, "%" G_GUINT64_FORMAT, dcc->pos);
 			EMIT_SIGNAL_TIMESTAMP (XP_TE_DCCRESUMEREQUEST, sess, nick,
 										  file_part (dcc->file), tbuf, NULL, 0,
 										  tags_data->timestamp);
@@ -2508,7 +2588,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 
 		port = atoi (word[8]);
 		addr = strtoul (word[7], NULL, 10);
-		size = BIG_STR_TO_INT (word[9]);
+		size = g_ascii_strtoull (word[9], NULL, 10);
 
 		if (port == 0) /* Passive dcc requested */
 			pasvid = atoi (word[10]);
@@ -2576,7 +2656,7 @@ dcc_show_list (struct session *sess)
 	{
 		dcc = (struct DCC *) list->data;
 		i++;
-		PrintTextf (sess, " %s  %-10.10s %-7.7s %-7"DCC_SFMT" %-7"DCC_SFMT" %s\n",
+		PrintTextf (sess, " %s  %-10.10s %-7.7s %-7" G_GUINT64_FORMAT " %-7" G_GUINT64_FORMAT " %s\n",
 					 dcctypes[dcc->type], dcc->nick,
 					 _(dccstat[dcc->dccstat].name), dcc->size, dcc->pos,
 					 file_part (dcc->file));
diff --git a/src/common/dcc.h b/src/common/dcc.h
index ade1dae7..e7115b32 100644
--- a/src/common/dcc.h
+++ b/src/common/dcc.h
@@ -39,17 +39,6 @@
 
 #define CPS_AVG_WINDOW 10
 
-/* can we do 64-bit dcc? */
-#if defined(G_GINT64_FORMAT) && defined(HAVE_STRTOULL)
-#define USE_DCC64
-/* we really get only 63 bits, since st_size is signed */
-#define DCC_SIZE gint64
-#define DCC_SFMT G_GINT64_FORMAT
-#else
-#define DCC_SIZE unsigned int
-#define DCC_SFMT "u"
-#endif
-
 struct DCC
 {
 	struct server *serv;
@@ -62,21 +51,21 @@ struct DCC
 	int wiotag;						/* writing/sending io tag */
 	int port;
 	int pasvid;						/* mIRC's passive DCC id */
-	int cps;
+	gint64 cps;
 	int resume_error;
 	int resume_errno;
 
 	GTimeVal lastcpstv, firstcpstv;
-	DCC_SIZE lastcpspos;
-	int maxcps;
+	goffset lastcpspos;
+	gint64 maxcps;
 
 	unsigned char ack_buf[4];	/* buffer for reading 4-byte ack */
 	int ack_pos;
 
-	DCC_SIZE size;
-	DCC_SIZE resumable;
-	DCC_SIZE ack;
-	DCC_SIZE pos;
+	guint64 size;
+	guint64 resumable;
+	guint64 ack;
+	guint64 pos;
 	time_t starttime;
 	time_t offertime;
 	time_t lasttime;
@@ -125,7 +114,7 @@ void dcc_check_timeouts (void);
 void dcc_change_nick (server *serv, char *oldnick, char *newnick);
 void dcc_notify_kill (struct server *serv);
 struct DCC *dcc_write_chat (char *nick, char *text);
-void dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive);
+void dcc_send (struct session *sess, char *to, char *file, gint64 maxcps, int passive);
 struct DCC *find_dcc (char *nick, char *file, int type);
 void dcc_get_nick (struct session *sess, char *nick);
 void dcc_chat (session *sess, char *nick, int passive);
diff --git a/src/common/fe.h b/src/common/fe.h
index 2ca15c60..a3bd2afa 100644
--- a/src/common/fe.h
+++ b/src/common/fe.h
@@ -88,11 +88,10 @@ void fe_progressbar_start (struct session *sess);
 void fe_progressbar_end (struct server *serv);
 void fe_print_text (struct session *sess, char *text, time_t stamp,
 					gboolean no_activity);
-void fe_userlist_insert (struct session *sess, struct User *newuser, int row, int sel);
+void fe_userlist_insert (struct session *sess, struct User *newuser, gboolean sel);
 int fe_userlist_remove (struct session *sess, struct User *user);
 void fe_userlist_rehash (struct session *sess, struct User *user);
 void fe_userlist_update (struct session *sess, struct User *user);
-void fe_userlist_move (struct session *sess, struct User *user, int new_row);
 void fe_userlist_numbers (struct session *sess);
 void fe_userlist_clear (struct session *sess);
 void fe_userlist_set_selected (struct session *sess);
@@ -179,7 +178,6 @@ typedef enum
 } feicon;
 void fe_tray_set_icon (feicon icon);
 void fe_tray_set_tooltip (const char *text);
-void fe_tray_set_balloon (const char *title, const char *text);
 void fe_open_chan_list (server *serv, char *filter, int do_refresh);
 const char *fe_get_default_font ();
 
diff --git a/src/common/hexchat.c b/src/common/hexchat.c
index 09afa445..a76db332 100644
--- a/src/common/hexchat.c
+++ b/src/common/hexchat.c
@@ -41,7 +41,9 @@
 #include "chanopt.h"
 #include "ignore.h"
 #include "hexchat-plugin.h"
+#include "inbound.h"
 #include "plugin.h"
+#include "plugin-identd.h"
 #include "plugin-timer.h"
 #include "notify.h"
 #include "server.h"
@@ -55,15 +57,6 @@
 #include <glib-object.h>			/* for g_type_init() */
 #endif
 
-#ifdef USE_OPENSSL
-#include <openssl/ssl.h>			/* SSL_() */
-#include "ssl.h"
-#endif
-
-#ifdef USE_MSPROXY
-#include "msproxy.h"
-#endif
-
 #ifdef USE_LIBPROXY
 #include <proxy.h>
 #endif
@@ -118,10 +111,6 @@ struct session *current_tab;
 struct session *current_sess = 0;
 struct hexchatprefs prefs;
 
-#ifdef USE_OPENSSL
-SSL_CTX *ctx = NULL;
-#endif
-
 #ifdef USE_LIBPROXY
 pxProxyFactory *libproxy_factory;
 #endif
@@ -221,7 +210,7 @@ find_dialog (server *serv, char *nick)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 session *
@@ -232,14 +221,14 @@ find_channel (server *serv, char *chan)
 	while (list)
 	{
 		sess = list->data;
-		if ((!serv || serv == sess->server) && sess->type == SESS_CHANNEL)
+		if ((serv == sess->server) && sess->type == SESS_CHANNEL)
 		{
 			if (!serv->p_cmp (chan, sess->channel))
 				return sess;
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 static void
@@ -269,7 +258,7 @@ lag_check (void)
 	unsigned long tim;
 	char tbuf[128];
 	time_t now = time (0);
-	int lag;
+	time_t lag;
 
 	tim = make_ping_time ();
 
@@ -279,16 +268,17 @@ lag_check (void)
 		if (serv->connected && serv->end_of_motd)
 		{
 			lag = now - serv->ping_recv;
-			if (prefs.hex_net_ping_timeout && lag > prefs.hex_net_ping_timeout && lag > 0)
+			if (prefs.hex_net_ping_timeout != 0 && lag > prefs.hex_net_ping_timeout && lag > 0)
 			{
-				sprintf (tbuf, "%d", lag);
+				sprintf (tbuf, "%" G_GINT64_FORMAT, (gint64) lag);
 				EMIT_SIGNAL (XP_TE_PINGTIMEOUT, serv->server_session, tbuf, NULL,
 								 NULL, NULL, 0);
 				if (prefs.hex_net_auto_reconnect)
 					serv->auto_reconnect (serv, FALSE, -1);
-			} else
+			}
+			else
 			{
-				snprintf (tbuf, sizeof (tbuf), "LAG%lu", tim);
+				g_snprintf (tbuf, sizeof (tbuf), "LAG%lu", tim);
 				serv->p_ping (serv, "", tbuf);
 				
 				if (!serv->lag_sent)
@@ -368,9 +358,6 @@ static int
 hexchat_misc_checks (void)		/* this gets called every 1/2 second */
 {
 	static int count = 0;
-#ifdef USE_MSPROXY
-	static int count2 = 0;
-#endif
 
 	count++;
 
@@ -386,15 +373,6 @@ hexchat_misc_checks (void)		/* this gets called every 1/2 second */
 		count = 0;
 	}
 
-#ifdef USE_MSPROXY	
-	count2++;
-	if (count2 >= 720)			/* 720 every 6 minutes */
-	{
-		msproxy_keepalive ();
-		count2 = 0;
-	}
-#endif
-
 	return 1;
 }
 
@@ -405,7 +383,6 @@ irc_init (session *sess)
 {
 	static int done_init = FALSE;
 	char *buf;
-	int i;
 
 	if (done_init)
 		return;
@@ -413,6 +390,7 @@ irc_init (session *sess)
 	done_init = TRUE;
 
 	plugin_add (sess, NULL, NULL, timer_plugin_init, NULL, NULL, FALSE);
+	plugin_add (sess, NULL, NULL, identd_plugin_init, identd_plugin_deinit, NULL, FALSE);
 
 #ifdef USE_PLUGIN
 	if (!arg_skip_plugins)
@@ -440,7 +418,8 @@ irc_init (session *sess)
 	
 	if (arg_urls != NULL)
 	{
-		for (i = 0; i < g_strv_length(arg_urls); i++)
+		guint i;
+		for (i = 0; i < g_strv_length (arg_urls); i++)
 		{
 			buf = g_strdup_printf ("%s %s", i==0? "server" : "newserver", arg_urls[i]);
 			handle_command (sess, buf, FALSE);
@@ -464,12 +443,7 @@ session_new (server *serv, char *from, int type, int focus)
 {
 	session *sess;
 
-	sess = malloc (sizeof (struct session));
-	if (sess == NULL)
-	{
-		return NULL;
-	}
-	memset (sess, 0, sizeof (struct session));
+	sess = g_new0 (struct session, 1);
 
 	sess->server = serv;
 	sess->logfd = -1;
@@ -488,7 +462,10 @@ session_new (server *serv, char *from, int type, int focus)
 	sess->lastact_idx = LACT_NONE;
 
 	if (from != NULL)
-		safe_strcpy (sess->channel, from, CHANLEN);
+	{
+		safe_strcpy(sess->channel, from, CHANLEN);
+		safe_strcpy(sess->session_name, from, CHANLEN);
+	}
 
 	sess_list = g_slist_prepend (sess_list, sess);
 
@@ -515,7 +492,6 @@ new_ircwindow (server *serv, char *name, int type, int focus)
 		break;
 	case SESS_DIALOG:
 		sess = session_new (serv, name, type, focus);
-		log_open_or_close (sess);
 		break;
 	default:
 /*	case SESS_CHANNEL:
@@ -530,6 +506,16 @@ new_ircwindow (server *serv, char *name, int type, int focus)
 	scrollback_load (sess);
 	if (sess->scrollwritten && sess->scrollback_replay_marklast)
 		sess->scrollback_replay_marklast (sess);
+	if (type == SESS_DIALOG)
+	{
+		struct User *user;
+
+		log_open_or_close (sess);
+
+		user = userlist_find_global (serv, name);
+		if (user && user->hostname)
+			set_topic (sess, user->hostname, user->hostname);
+	}
 	plugin_emit_dummy_print (sess, "Open Context");
 
 	return sess;
@@ -548,9 +534,8 @@ exec_notify_kill (session * sess)
 		waitpid (re->childpid, NULL, WNOHANG);
 		fe_input_remove (re->iotag);
 		close (re->myfd);
-		if (re->linebuf)
-			free(re->linebuf);
-		free (re);
+		g_free(re->linebuf);
+		g_free (re);
 	}
 #endif
 }
@@ -656,10 +641,8 @@ session_free (session *killsess)
 	send_quit_or_part (killsess);
 
 	history_free (&killsess->history);
-	if (killsess->topic)
-		free (killsess->topic);
-	if (killsess->current_modes)
-		free (killsess->current_modes);
+	g_free (killsess->topic);
+	g_free (killsess->current_modes);
 
 	fe_session_callback (killsess);
 
@@ -670,7 +653,7 @@ session_free (session *killsess)
 			current_sess = sess_list->data;
 	}
 
-	free (killsess);
+	g_free (killsess);
 
 	if (!sess_list && !in_hexchat_exit)
 		hexchat_exit ();						/* sess_list is empty, quit! */
@@ -784,20 +767,15 @@ static void
 xchat_init (void)
 {
 	char buf[3068];
-	const char *cs = NULL;
 
 #ifdef WIN32
 	WSADATA wsadata;
 
-#ifdef USE_IPV6
 	if (WSAStartup(0x0202, &wsadata) != 0)
 	{
 		MessageBox (NULL, "Cannot find winsock 2.2+", "Error", MB_OK);
 		exit (0);
 	}
-#else
-	WSAStartup(0x0101, &wsadata);
-#endif	/* !USE_IPV6 */
 #endif	/* !WIN32 */
 
 #ifdef USE_SIGACTION
@@ -826,15 +804,12 @@ xchat_init (void)
 #endif
 #endif
 
-	if (g_get_charset (&cs))
-		prefs.utf8_locale = TRUE;
-
 	load_text_events ();
 	sound_load ();
 	notify_load ();
 	ignore_load ();
 
-	snprintf (buf, sizeof (buf),
+	g_snprintf (buf, sizeof (buf),
 		"NAME %s~%s~\n"				"CMD query %%s\n\n"\
 		"NAME %s~%s~\n"				"CMD send %%s\n\n"\
 		"NAME %s~%s~\n"				"CMD whois %%s %%s\n\n"\
@@ -890,7 +865,7 @@ xchat_init (void)
 
 	list_loadconf ("popup.conf", &popup_list, buf);
 
-	snprintf (buf, sizeof (buf),
+	g_snprintf (buf, sizeof (buf),
 		"NAME %s\n"				"CMD part\n\n"
 		"NAME %s\n"				"CMD getstr # join \"%s\"\n\n"
 		"NAME %s\n"				"CMD quote LINKS\n\n"
@@ -904,7 +879,7 @@ xchat_init (void)
 				_("Hide Version"));
 	list_loadconf ("usermenu.conf", &usermenu_list, buf);
 
-	snprintf (buf, sizeof (buf),
+	g_snprintf (buf, sizeof (buf),
 		"NAME %s\n"		"CMD op %%a\n\n"
 		"NAME %s\n"		"CMD deop %%a\n\n"
 		"NAME %s\n"		"CMD ban %%s\n\n"
@@ -921,7 +896,7 @@ xchat_init (void)
 				_("Dialog"));
 	list_loadconf ("buttons.conf", &button_list, buf);
 
-	snprintf (buf, sizeof (buf),
+	g_snprintf (buf, sizeof (buf),
 		"NAME %s\n"				"CMD whois %%s %%s\n\n"
 		"NAME %s\n"				"CMD send %%s\n\n"
 		"NAME %s\n"				"CMD dcc chat %%s\n\n"
@@ -1021,29 +996,37 @@ main (int argc, char *argv[])
 	int i;
 	int ret;
 
-	srand (time (0));	/* CL: do this only once! */
+#ifdef WIN32
+	HRESULT coinit_result;
+#endif
+
+	srand ((unsigned int) time (NULL)); /* CL: do this only once! */
 
 	/* We must check for the config dir parameter, otherwise load_config() will behave incorrectly.
 	 * load_config() must come before fe_args() because fe_args() calls gtk_init() which needs to
 	 * know the language which is set in the config. The code below is copy-pasted from fe_args()
 	 * for the most part. */
-	if (argc >= 3)
+	if (argc >= 2)
 	{
-		for (i = 1; i < argc - 1; i++)
+		for (i = 1; i < argc; i++)
 		{
-			if (strcmp (argv[i], "-d") == 0)
+			if ((strcmp (argv[i], "-d") == 0 || strcmp (argv[i], "--cfgdir") == 0)
+				&& i + 1 < argc)
 			{
-				if (xdir)
-				{
-					g_free (xdir);
-				}
-
-				xdir = strdup (argv[i + 1]);
+				xdir = g_strdup (argv[i + 1]);
+			}
+			else if (strncmp (argv[i], "--cfgdir=", 9) == 0)
+			{
+				xdir = g_strdup (argv[i] + 9);
+			}
 
+			if (xdir != NULL)
+			{
 				if (xdir[strlen (xdir) - 1] == G_DIR_SEPARATOR)
 				{
 					xdir[strlen (xdir) - 1] = 0;
 				}
+				break;
 			}
 		}
 	}
@@ -1067,10 +1050,6 @@ main (int argc, char *argv[])
 	/* we MUST do this after load_config () AND before fe_init (thus gtk_init) otherwise it will fail */
 	set_locale ();
 
-#ifdef SOCKS
-	SOCKSinit (argv[0]);
-#endif
-
 	ret = fe_args (argc, argv);
 	if (ret != -1)
 		return ret;
@@ -1083,6 +1062,14 @@ main (int argc, char *argv[])
 	libproxy_factory = px_proxy_factory_new();
 #endif
 
+#ifdef WIN32
+	coinit_result = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
+	if (SUCCEEDED (coinit_result))
+	{
+		CoInitializeSecurity (NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
+	}
+#endif
+
 	fe_init ();
 
 	/* This is done here because cfgfiles.c is too early in
@@ -1110,13 +1097,15 @@ main (int argc, char *argv[])
 
 	fe_main ();
 
-#ifdef USE_LIBPROXY
-	px_proxy_factory_free(libproxy_factory);
+#ifdef WIN32
+	if (SUCCEEDED (coinit_result))
+	{
+		CoUninitialize ();
+	}
 #endif
 
-#ifdef USE_OPENSSL
-	if (ctx)
-		_SSL_context_free (ctx);
+#ifdef USE_LIBPROXY
+	px_proxy_factory_free(libproxy_factory);
 #endif
 
 #ifdef WIN32
diff --git a/src/common/hexchat.h b/src/common/hexchat.h
index bbf32da5..652dcf1d 100644
--- a/src/common/hexchat.h
+++ b/src/common/hexchat.h
@@ -22,6 +22,7 @@
 #include <glib.h>
 #include <glib/gstdio.h>
 #include <glib/gi18n.h>
+#include <gio/gio.h>
 
 #include <time.h>			/* need time_t */
 
@@ -36,22 +37,7 @@
 #endif
 
 #include "history.h"
-
-#ifndef HAVE_SNPRINTF
-#define snprintf g_snprintf
-#endif
-
-#ifndef HAVE_VSNPRINTF
-#define vsnprintf _vsnprintf
-#endif
-
-#ifdef SOCKS
-#ifdef __sgi
-#include <sys/time.h>
-#define INCLUDE_PROTOTYPES 1
-#endif
-#include <socks.h>
-#endif
+#include "tree.h"
 
 #ifdef USE_OPENSSL
 #include <openssl/ssl.h>		  /* SSL_() */
@@ -262,6 +248,7 @@ struct hexchatprefs
 	int hex_gui_search_pos;
 	int hex_gui_slist_select;
 	int hex_gui_tab_layout;
+	int hex_gui_tab_middleclose;
 	int hex_gui_tab_newtofront;
 	int hex_gui_tab_pos;
 	int hex_gui_tab_small;
@@ -277,7 +264,7 @@ struct hexchatprefs
 	int hex_gui_win_state;
 	int hex_gui_win_top;
 	int hex_gui_win_width;
-	int hex_input_balloon_time;
+	int hex_identd_port;
 	int hex_irc_ban_type;
 	int hex_irc_join_delay;
 	int hex_irc_notice_pos;
@@ -329,7 +316,6 @@ struct hexchatprefs
 	guint32 dcc_ip;
 
 	unsigned int wait_on_exit;	/* wait for logs to be flushed to disk IF we're connected */
-	unsigned int utf8_locale;
 
 	/* Tells us if we need to save, only when they've been edited.
 		This is so that we continue using internal defaults (which can
@@ -382,12 +368,12 @@ typedef struct session
 	guint8 text_strip;
 
 	struct server *server;
-	void *usertree_alpha;			/* pure alphabetical tree */
-	void *usertree;					/* ordered with Ops first */
+	tree *usertree;					/* alphabetical tree */
 	struct User *me;					/* points to myself in the usertree */
 	char channel[CHANLEN];
 	char waitchannel[CHANLEN];		  /* waiting to join channel (/join sent) */
 	char willjoinchannel[CHANLEN];	  /* will issue /join for this channel */
+	char session_name[CHANLEN];		 /* the name of the session, should not modified */
 	char channelkey[64];			  /* XXX correct max length? */
 	int limit;						  /* channel user limit */
 	int logfd;
@@ -434,14 +420,6 @@ typedef struct session
 	void (*scrollback_replay_marklast) (struct session *sess);
 } session;
 
-struct msproxy_state_t
-{
-	gint32				clientid;
-	gint32				serverid;
-	unsigned char		seq_recv;		/* seq number of last packet recv.	*/
-	unsigned char		seq_sent;		/* seq number of last packet sent.	*/
-};
-
 /* SASL Mechanisms */
 #define MECH_PLAIN 0
 #define MECH_BLOWFISH 1
@@ -499,9 +477,9 @@ typedef struct server
 	int proxy_sok;				/* Additional information for MS Proxy beast */
 	int proxy_sok4;
 	int proxy_sok6;
-	struct msproxy_state_t msp_state;
 	int id;					/* unique ID number (for plugin API) */
 #ifdef USE_OPENSSL
+	SSL_CTX *ctx;
 	SSL *ssl;
 	int ssl_do_connect_tag;
 #else
@@ -554,7 +532,10 @@ typedef struct server
 	time_t ping_recv;					/* when we last got a ping reply */
 	time_t away_time;					/* when we were marked away */
 
-	char *encoding;					/* NULL for system */
+	char *encoding;
+	GIConv read_converter;  /* iconv converter for converting from server encoding to UTF-8. */
+	GIConv write_converter; /* iconv converter for converting from UTF-8 to server encoding. */
+
 	GSList *favlist;			/* list of channels & keys to join */
 
 	unsigned int motd_skipped:1;
@@ -587,8 +568,6 @@ typedef struct server
 	unsigned int have_except:1;	/* ban exemptions +e */
 	unsigned int have_invite:1;	/* invite exemptions +I */
 	unsigned int have_cert:1;	/* have loaded a cert */
-	unsigned int using_cp1255:1;	/* encoding is CP1255/WINDOWS-1255? */
-	unsigned int using_irc:1;		/* encoding is "IRC" (CP1252/UTF-8 hybrid)? */
 	unsigned int use_who:1;			/* whether to use WHO command to get dcc_ip */
 	unsigned int sasl_mech;			/* mechanism for sasl auth */
 	unsigned int sent_saslauth:1;	/* have sent AUTHENICATE yet */
@@ -631,7 +610,4 @@ struct popup
 /* CL: get a random int in the range [0..n-1]. DON'T use rand() % n, it gives terrible results. */
 #define RAND_INT(n) ((int)(rand() / (RAND_MAX + 1.0) * (n)))
 
-#define hexchat_filename_from_utf8 g_filename_from_utf8
-#define hexchat_filename_to_utf8 g_filename_to_utf8
-
 #endif
diff --git a/src/common/history.c b/src/common/history.c
index 1acd3327..23a8463e 100644
--- a/src/common/history.c
+++ b/src/common/history.c
@@ -18,14 +18,14 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <glib.h>
 #include "history.h"
 
 void
 history_add (struct history *his, char *text)
 {
-	if (his->lines[his->realpos])
-		free (his->lines[his->realpos]);
-	his->lines[his->realpos] = strdup (text);
+	g_free (his->lines[his->realpos]);
+	his->lines[his->realpos] = g_strdup (text);
 	his->realpos++;
 	if (his->realpos == HISTORY_SIZE)
 		his->realpos = 0;
@@ -40,7 +40,7 @@ history_free (struct history *his)
 	{
 		if (his->lines[i])
 		{
-			free (his->lines[i]);
+			g_free (his->lines[i]);
 			his->lines[i] = 0;
 		}
 	}
@@ -52,7 +52,7 @@ history_down (struct history *his)
 	int next;
 
 	if (his->pos == his->realpos)	/* allow down only after up */
-		return 0;
+		return NULL;
 	if (his->realpos == 0)
 	{
 		if (his->pos == HISTORY_SIZE - 1)
@@ -79,7 +79,7 @@ history_down (struct history *his)
 		return his->lines[his->pos];
 	}
 
-	return 0;
+	return NULL;
 }
 
 char *
@@ -90,11 +90,11 @@ history_up (struct history *his, char *current_text)
 	if (his->realpos == HISTORY_SIZE - 1)
 	{
 		if (his->pos == 0)
-			return 0;
+			return NULL;
 	} else
 	{
 		if (his->pos == his->realpos + 1)
-			return 0;
+			return NULL;
 	}
 
 	next = HISTORY_SIZE - 1;
@@ -117,5 +117,5 @@ history_up (struct history *his, char *current_text)
 		return his->lines[his->pos];
 	}
 
-	return 0;
+	return NULL;
 }
diff --git a/src/common/identd.c b/src/common/identd.c
deleted file mode 100644
index c4050929..00000000
--- a/src/common/identd.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* HexChat
- * Copyright (C) 1998-2010 Peter Zelezny.
- * Copyright (C) 2009-2013 Berke Viktor.
- *
- * 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
- */
-
-/* simple identd server for HexChat under Win32 */
-
-#include "inet.h"
-#include "hexchat.h"
-#include "hexchatc.h"
-#include "text.h"
-
-static int identd_is_running = FALSE;
-#ifdef USE_IPV6
-static int identd_ipv6_is_running = FALSE;
-#endif
-
-static int
-identd (char *username)
-{
-	int sok, read_sok, len;
-	char *p;
-	char buf[256];
-	char outbuf[256];
-	char ipbuf[INET_ADDRSTRLEN];
-	struct sockaddr_in addr;
-
-	sok = socket (AF_INET, SOCK_STREAM, 0);
-	if (sok == INVALID_SOCKET)
-	{
-		free (username);
-		return 0;
-	}
-
-	len = 1;
-	setsockopt (sok, SOL_SOCKET, SO_REUSEADDR, (char *) &len, sizeof (len));
-
-	memset (&addr, 0, sizeof (addr));
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons (113);
-
-	if (bind (sok, (struct sockaddr *) &addr, sizeof (addr)) == SOCKET_ERROR)
-	{
-		closesocket (sok);
-		free (username);
-		return 0;
-	}
-
-	if (listen (sok, 1) == SOCKET_ERROR)
-	{
-		closesocket (sok);
-		free (username);
-		return 0;
-	}
-
-	len = sizeof (addr);
-	read_sok = accept (sok, (struct sockaddr *) &addr, &len);
-	closesocket (sok);
-	if (read_sok == INVALID_SOCKET)
-	{
-		free (username);
-		return 0;
-	}
-
-	identd_is_running = FALSE;
-
-#if 0	/* causes random crashes, probably due to CreateThread */
-	EMIT_SIGNAL (XP_TE_IDENTD, current_sess, inet_ntoa (addr.sin_addr), username, NULL, NULL, 0);
-#endif
-	inet_ntop (AF_INET, &addr.sin_addr, ipbuf, sizeof (ipbuf));
-	snprintf (outbuf, sizeof (outbuf), "*\tServicing ident request from %s as %s\n", ipbuf, username);
-	PrintText (current_sess, outbuf);
-
-	recv (read_sok, buf, sizeof (buf) - 1, 0);
-	buf[sizeof (buf) - 1] = 0;	  /* ensure null termination */
-
-	p = strchr (buf, ',');
-	if (p)
-	{
-		snprintf (outbuf, sizeof (outbuf) - 1, "%d, %d : USERID : UNIX : %s\r\n",
-					 atoi (buf), atoi (p + 1), username);
-		outbuf[sizeof (outbuf) - 1] = 0;	/* ensure null termination */
-		send (read_sok, outbuf, strlen (outbuf), 0);
-	}
-
-	sleep (1);
-	closesocket (read_sok);
-	free (username);
-
-	return 0;
-}
-
-#ifdef USE_IPV6
-static int
-identd_ipv6 (char *username)
-{
-	int sok, read_sok, len;
-	char *p;
-	char buf[256];
-	char outbuf[256];
-	char ipbuf[INET6_ADDRSTRLEN];
-	struct sockaddr_in6 addr;
-
-	sok = socket (AF_INET6, SOCK_STREAM, 0);
-	if (sok == INVALID_SOCKET)
-	{
-		free (username);
-		return 0;
-	}
-
-	len = 1;
-	setsockopt (sok, SOL_SOCKET, SO_REUSEADDR, (char *) &len, sizeof (len));
-
-	memset (&addr, 0, sizeof (addr));
-	addr.sin6_family = AF_INET6;
-	addr.sin6_port = htons (113);
-
-	if (bind (sok, (struct sockaddr *) &addr, sizeof (addr)) == SOCKET_ERROR)
-	{
-		closesocket (sok);
-		free (username);
-		return 0;
-	}
-
-	if (listen (sok, 1) == SOCKET_ERROR)
-	{
-		closesocket (sok);
-		free (username);
-		return 0;
-	}
-
-	len = sizeof (addr);
-	read_sok = accept (sok, (struct sockaddr *) &addr, &len);
-	closesocket (sok);
-	if (read_sok == INVALID_SOCKET)
-	{
-		free (username);
-		return 0;
-	}
-
-	identd_ipv6_is_running = FALSE;
-
-	inet_ntop (AF_INET6, &addr.sin6_addr, ipbuf, sizeof (ipbuf));
-	snprintf (outbuf, sizeof (outbuf), "*\tServicing ident request from %s as %s\n", ipbuf, username);
-	PrintText (current_sess, outbuf);
-
-	recv (read_sok, buf, sizeof (buf) - 1, 0);
-	buf[sizeof (buf) - 1] = 0;	  /* ensure null termination */
-
-	p = strchr (buf, ',');
-	if (p)
-	{
-		snprintf (outbuf, sizeof (outbuf) - 1, "%d, %d : USERID : UNIX : %s\r\n", atoi (buf), atoi (p + 1), username);
-		outbuf[sizeof (outbuf) - 1] = 0;	/* ensure null termination */
-		send (read_sok, outbuf, strlen (outbuf), 0);
-	}
-
-	sleep (1);
-	closesocket (read_sok);
-	free (username);
-
-	return 0;
-}
-#endif
-
-void
-identd_start (char *username)
-{
-	DWORD tid;
-
-#ifdef USE_IPV6
-	DWORD tidv6;
-	if (identd_ipv6_is_running == FALSE)
-	{
-		identd_ipv6_is_running = TRUE;
-		CloseHandle (CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) identd_ipv6,
-						 strdup (username), 0, &tidv6));
-	}
-#endif
-
-	if (identd_is_running == FALSE)
-	{
-		identd_is_running = TRUE;
-		CloseHandle (CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) identd,
-						 strdup (username), 0, &tid));
-	}
-}
diff --git a/src/common/ignore.c b/src/common/ignore.c
index 045224ba..6085b657 100644
--- a/src/common/ignore.c
+++ b/src/common/ignore.c
@@ -53,7 +53,7 @@ static int ignored_total = 0;
 struct ignore *
 ignore_exists (char *mask)
 {
-	struct ignore *ig = 0;
+	struct ignore *ig = NULL;
 	GSList *list;
 
 	list = ignore_list;
@@ -79,7 +79,7 @@ ignore_exists (char *mask)
 int
 ignore_add (char *mask, int type, gboolean overwrite)
 {
-	struct ignore *ig = 0;
+	struct ignore *ig = NULL;
 	int change_only = FALSE;
 
 	/* first check if it's already ignored */
@@ -88,12 +88,9 @@ ignore_add (char *mask, int type, gboolean overwrite)
 		change_only = TRUE;
 
 	if (!change_only)
-		ig = malloc (sizeof (struct ignore));
+		ig = g_new (struct ignore, 1);
 
-	if (!ig)
-		return 0;
-
-	ig->mask = strdup (mask);
+	ig->mask = g_strdup (mask);
 
 	if (!overwrite && change_only)
 		ig->type |= type;
@@ -125,7 +122,7 @@ ignore_showlist (session *sess)
 		ig = list->data;
 		i++;
 
-		snprintf (tbuf, sizeof (tbuf), " %-25s ", ig->mask);
+		g_snprintf (tbuf, sizeof (tbuf), " %-25s ", ig->mask);
 		if (ig->type & IG_PRIV)
 			strcat (tbuf, _("YES  "));
 		else
@@ -192,8 +189,8 @@ ignore_del (char *mask, struct ignore *ig)
 	if (ig)
 	{
 		ignore_list = g_slist_remove (ignore_list, ig);
-		free (ig->mask);
-		free (ig);
+		g_free (ig->mask);
+		g_free (ig);
 		fe_ignore_update (1);
 		return TRUE;
 	}
@@ -265,7 +262,7 @@ ignore_read_next_entry (char *my_cfg, struct ignore *ignore)
 		my_cfg = cfg_get_str (my_cfg, "mask", tbuf, sizeof (tbuf));
 		if (!my_cfg)
 			return NULL;
-		ignore->mask = strdup (tbuf);
+		ignore->mask = g_strdup (tbuf);
 	}
 	if (my_cfg)
 	{
@@ -281,7 +278,7 @@ ignore_load ()
 	struct ignore *ignore;
 	struct stat st;
 	char *cfg, *my_cfg;
-	int fh, i;
+	int fh;
 
 	fh = hexchat_open_file ("ignore.conf", O_RDONLY, 0, 0);
 	if (fh != -1)
@@ -289,22 +286,18 @@ ignore_load ()
 		fstat (fh, &st);
 		if (st.st_size)
 		{
-			cfg = malloc (st.st_size + 1);
-			cfg[0] = '\0';
-			i = read (fh, cfg, st.st_size);
-			if (i >= 0)
-				cfg[i] = '\0';
+			cfg = g_malloc0 (st.st_size + 1);
+			read (fh, cfg, st.st_size);
 			my_cfg = cfg;
 			while (my_cfg)
 			{
-				ignore = malloc (sizeof (struct ignore));
-				memset (ignore, 0, sizeof (struct ignore));
+				ignore = g_new0 (struct ignore, 1);
 				if ((my_cfg = ignore_read_next_entry (my_cfg, ignore)))
 					ignore_list = g_slist_prepend (ignore_list, ignore);
 				else
-					free (ignore);
+					g_free (ignore);
 			}
-			free (cfg);
+			g_free (cfg);
 		}
 		close (fh);
 	}
@@ -326,7 +319,7 @@ ignore_save ()
 			ig = (struct ignore *) temp->data;
 			if (!(ig->type & IG_NOSAVE))
 			{
-				snprintf (buf, sizeof (buf), "mask = %s\ntype = %u\n\n",
+				g_snprintf (buf, sizeof (buf), "mask = %s\ntype = %u\n\n",
 							 ig->mask, ig->type);
 				write (fh, buf, strlen (buf));
 			}
@@ -379,9 +372,9 @@ flood_check (char *nick, char *ip, server *serv, session *sess, int what)	/*0=ct
 					for (i = 0; i < 128; i++)
 						if (ip[i] == '@')
 							break;
-					snprintf (real_ip, sizeof (real_ip), "*!*%s", &ip[i]);
+					g_snprintf (real_ip, sizeof (real_ip), "*!*%s", &ip[i]);
 
-					snprintf (buf, sizeof (buf),
+					g_snprintf (buf, sizeof (buf),
 								 _("You are being CTCP flooded from %s, ignoring %s\n"),
 								 nick, real_ip);
 					PrintText (sess, buf);
@@ -406,7 +399,7 @@ flood_check (char *nick, char *ip, server *serv, session *sess, int what)	/*0=ct
 				serv->msg_counter++;
 				if (serv->msg_counter == prefs.hex_flood_msg_num)	/*if we reached the maximun numbers of ctcp in the seconds limits */
 				{
-					snprintf (buf, sizeof (buf),
+					g_snprintf (buf, sizeof (buf),
 					 _("You are being MSG flooded from %s, setting gui_autoopen_dialog OFF.\n"),
 								 ip);
 					PrintText (sess, buf);
diff --git a/src/common/inbound.c b/src/common/inbound.c
index b80553b3..ef26890b 100644
--- a/src/common/inbound.c
+++ b/src/common/inbound.c
@@ -33,8 +33,6 @@
 #define WANTDNS
 #include "inet.h"
 
-#include <gio/gio.h>
-
 #include "hexchat.h"
 #include "util.h"
 #include "ignore.h"
@@ -64,7 +62,7 @@ clear_channel (session *sess)
 
 	if (sess->current_modes)
 	{
-		free (sess->current_modes);
+		g_free (sess->current_modes);
 		sess->current_modes = NULL;
 	}
 
@@ -83,9 +81,17 @@ clear_channel (session *sess)
 void
 set_topic (session *sess, char *topic, char *stripped_topic)
 {
-	if (sess->topic)
-		free (sess->topic);
-	sess->topic = strdup (stripped_topic);
+	/* The topic of dialogs are the users hostname which is logged is new */
+	if (sess->type == SESS_DIALOG && (!sess->topic || strcmp(sess->topic, stripped_topic))
+		&& sess->logfd != -1)
+	{
+		char tbuf[1024];
+		g_snprintf (tbuf, sizeof (tbuf), "[%s has address %s]\n", sess->channel, stripped_topic);
+		write (sess->logfd, tbuf, strlen (tbuf));
+	}
+
+	g_free (sess->topic);
+	sess->topic = g_strdup (stripped_topic);
 	fe_set_topic (sess, topic, stripped_topic);
 }
 
@@ -121,7 +127,7 @@ find_session_from_nick (char *nick, server *serv)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 static session *
@@ -182,16 +188,7 @@ inbound_privmsg (server *serv, char *from, char *ip, char *text, int id,
 		}
 
 		if (ip && ip[0])
-		{
-			if (prefs.hex_irc_logging && sess->logfd != -1 &&
-				(!sess->topic || strcmp(sess->topic, ip)))
-			{
-				char tbuf[1024];
-				snprintf (tbuf, sizeof (tbuf), "[%s has address %s]\n", from, ip);
-				write (sess->logfd, tbuf, strlen (tbuf));
-			}
 			set_topic (sess, ip, ip);
-		}
 		inbound_chanmsg (serv, NULL, NULL, from, text, FALSE, id, tags_data);
 		return;
 	}
@@ -558,7 +555,7 @@ find_unused_session (server *serv)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 static session *
@@ -576,7 +573,7 @@ find_session_from_waitchannel (char *chan, struct server *serv)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 void
@@ -682,7 +679,8 @@ inbound_nameslist (server *serv, char *chan, char *names,
 	char **name_list;
 	char *host, *nopre_name;
 	char name[NICKLEN];
-	int i, offset;
+	int i;
+	size_t offset;
 
 	sess = find_channel (serv, chan);
 	if (!sess)
@@ -916,7 +914,7 @@ inbound_ping_reply (session *sess, char *timestring, char *from,
 										  tags_data->timestamp);
 	} else
 	{
-		snprintf (outbuf, sizeof (outbuf), "%ld.%03ld", dif / 1000, dif % 1000);
+		g_snprintf (outbuf, sizeof (outbuf), "%ld.%03ld", dif / 1000, dif % 1000);
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_PINGREP, sess, from, outbuf, NULL, NULL, 0,
 									  tags_data->timestamp);
 	}
@@ -934,7 +932,7 @@ find_session_from_type (int type, server *serv)
 			return sess;
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 void
@@ -969,14 +967,14 @@ inbound_notice (server *serv, char *to, char *nick, char *msg, char *ip, int id,
 				/* guess where chanserv meant to post this -sigh- */
 				if (!g_ascii_strcasecmp (nick, "ChanServ") && !find_dialog (serv, nick))
 				{
-					char *dest = strdup (msg + 1);
+					char *dest = g_strdup (msg + 1);
 					char *end = strchr (dest, ']');
 					if (end)
 					{
 						*end = 0;
 						sess = find_channel (serv, dest);
 					}
-					free (dest);
+					g_free (dest);
 				}
 			}
 			if (!sess)
@@ -1455,8 +1453,7 @@ inbound_user_info (session *sess, char *chan, char *user, char *host,
 
 	if (user && host)
 	{
-		uhost = g_malloc (strlen (user) + strlen (host) + 2);
-		sprintf (uhost, "%s@%s", user, host);
+		uhost = g_strdup_printf ("%s@%s", user, host);
 	}
 
 	if (chan)
diff --git a/src/common/inet.h b/src/common/inet.h
index 990415be..7056d473 100644
--- a/src/common/inet.h
+++ b/src/common/inet.h
@@ -47,13 +47,9 @@
 
 #else
 
-#include "../../config.h"
-#ifdef USE_IPV6
+#include "config.h"
 #include <winsock2.h>
 #include <ws2tcpip.h>
-#else
-#include <winsock2.h>
-#endif
 
 #define set_blocking(sok)	{ \
 									unsigned long zero = 0; \
diff --git a/src/common/make-te.c b/src/common/make-te.c
index 309eec2f..834646ef 100644
--- a/src/common/make-te.c
+++ b/src/common/make-te.c
@@ -42,7 +42,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-int main()
+int main(void)
 {
 	char name[512];
 	char num[512];
@@ -87,9 +87,11 @@ int main()
 		if (i + 1 < max)
 		{
 			fprintf(stderr, "\t%s,\t\t%s,\n", defines[i], defines[i+1]);
+			free (defines[i]);
 			i++;
 		} else
 			fprintf(stderr, "\t%s,\n", defines[i]);
+		free (defines[i]);
 		i++;
 	}
 	fprintf(stderr, "\tNUM_XP\n};\n");
diff --git a/src/common/make-te.vcxproj b/src/common/make-te.vcxproj
index e9b4c533..24d8f9b6 100644
--- a/src/common/make-te.vcxproj
+++ b/src/common/make-te.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>Application</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,82 +20,30 @@
     <RootNamespace>makete</RootNamespace>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-    <Import Project="..\..\win32\hexchat.props" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-    <Import Project="..\..\win32\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <LinkIncremental>false</LinkIncremental>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <LinkIncremental>false</LinkIncremental>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+  <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  <Import Project="..\..\win32\hexchat.props" />

+  <PropertyGroup>

+    <OutDir>$(HexChatLib)</OutDir>

   </PropertyGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

     </ClCompile>

     <Link>

       <SubSystem>Console</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

     </Link>

-    <PostBuildEvent>

-      <Command>"$(HexChatBin)make-te.exe" &lt; "$(ProjectDir)textevents.in" &gt; "$(ProjectDir)textevents.h" 2&gt; "$(ProjectDir)textenums.h"</Command>

-    </PostBuildEvent>

   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

     </ClCompile>

     <Link>

       <SubSystem>Console</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

     </Link>

-    <PostBuildEvent>

-      <Command>"$(HexChatBin)make-te.exe" &lt; "$(ProjectDir)textevents.in" &gt; "$(ProjectDir)textevents.h" 2&gt; "$(ProjectDir)textenums.h"</Command>

-    </PostBuildEvent>

   </ItemDefinitionGroup>

   <ItemGroup>

     <ClCompile Include="make-te.c" />

   </ItemGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
+</Project>

diff --git a/src/common/modes.c b/src/common/modes.c
index b7cd471f..c65bf279 100644
--- a/src/common/modes.c
+++ b/src/common/modes.c
@@ -331,7 +331,7 @@ record_chan_mode (session *sess, char sign, char mode, char *arg)
 				current = g_string_erase(current, argument_offset+1, argument_length-1);
 				current = g_string_insert(current, argument_offset+1, arg);
 
-				free(sess->current_modes);
+				g_free(sess->current_modes);
 				sess->current_modes = g_string_free(current, FALSE);
 			}
 		}
@@ -348,7 +348,7 @@ record_chan_mode (session *sess, char sign, char mode, char *arg)
 				current = g_string_append(current, arg);
 			}
 
-			free(sess->current_modes);
+			g_free(sess->current_modes);
 			sess->current_modes = g_string_free(current, FALSE);
 		}
 	}
@@ -361,7 +361,7 @@ record_chan_mode (session *sess, char sign, char mode, char *arg)
 		/* remove the mode character */
 		current = g_string_erase(current, mode_pos, 1);
 
-		free(sess->current_modes);
+		g_free(sess->current_modes);
 		sess->current_modes = g_string_free(current, FALSE);
 	}
 }
@@ -374,12 +374,13 @@ mode_cat (char *str, char *addition)
 	if (str)
 	{
 		len = strlen (str) + strlen (addition) + 2;
-		str = realloc (str, len);
+		str = g_realloc (str, len);
 		strcat (str, " ");
 		strcat (str, addition);
-	} else
+	}
+	else
 	{
-		str = strdup (addition);
+		str = g_strdup (addition);
 	}
 
 	return str;
@@ -560,12 +561,12 @@ handle_single_mode (mode_run *mr, char sign, char mode, char *nick,
 	{
 		if (*arg)
 		{
-			char *buf = malloc (strlen (chan) + strlen (arg) + 2);
-			sprintf (buf, "%s %s", chan, arg);
+			char *buf = g_strdup_printf ("%s %s", chan, arg);
 			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMODEGEN, sess, nick, outbuf,
 										  outbuf + 2, buf, 0, tags_data->timestamp);
-			free (buf);
-		} else
+			g_free (buf);
+		}
+		else
 			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMODEGEN, sess, nick, outbuf,
 										  outbuf + 2, chan, 0, tags_data->timestamp);
 	}
@@ -635,7 +636,7 @@ mode_print_grouped (session *sess, char *nick, mode_run *mr,
 	{
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANOP, sess, nick, mr->op, NULL, NULL, 0,
 									  tags_data->timestamp);
-		free (mr->op);
+		g_free(mr->op);
 		mr->op = NULL;
 	}
 
@@ -643,7 +644,7 @@ mode_print_grouped (session *sess, char *nick, mode_run *mr,
 	{
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANDEOP, sess, nick, mr->deop, NULL, NULL,
 									  0, tags_data->timestamp);
-		free (mr->deop);
+		g_free(mr->deop);
 		mr->deop = NULL;
 	}
 
@@ -651,7 +652,7 @@ mode_print_grouped (session *sess, char *nick, mode_run *mr,
 	{
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANVOICE, sess, nick, mr->voice, NULL, NULL,
 									  0, tags_data->timestamp);
-		free (mr->voice);
+		g_free(mr->voice);
 		mr->voice = NULL;
 	}
 
@@ -659,7 +660,7 @@ mode_print_grouped (session *sess, char *nick, mode_run *mr,
 	{
 		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANDEVOICE, sess, nick, mr->devoice, NULL,
 									  NULL, 0, tags_data->timestamp);
-		free (mr->devoice);
+		g_free(mr->devoice);
 		mr->devoice = NULL;
 	}
 }
@@ -677,10 +678,10 @@ handle_mode (server * serv, char *word[], char *word_eol[],
 	char *argstr;
 	char sign;
 	int len;
-	int arg;
-	int i, num_args;
+	size_t arg;
+	size_t i, num_args;
 	int num_modes;
-	int offset = 3;
+	size_t offset = 3;
 	int all_modes_have_args = FALSE;
 	int using_front_tab = FALSE;
 	mode_run mr;
@@ -717,9 +718,8 @@ handle_mode (server * serv, char *word[], char *word_eol[],
 
 	if (numeric_324 && !using_front_tab)
 	{
-		if (sess->current_modes)
-			free (sess->current_modes);
-		sess->current_modes = strdup (word_eol[offset+1]);
+		g_free (sess->current_modes);
+		sess->current_modes = g_strdup (word_eol[offset+1]);
 	}
 
 	sign = *modes;
@@ -762,7 +762,7 @@ handle_mode (server * serv, char *word[], char *word_eol[],
 			break;
 		default:
 			argstr = "";
-			if ((all_modes_have_args || mode_has_arg (serv, sign, *modes)) && arg < (num_args+1))
+			if ((all_modes_have_args || mode_has_arg (serv, sign, *modes)) && arg < (num_args + 1))
 			{
 				arg++;
 				argstr = word[arg + offset];
@@ -799,30 +799,29 @@ inbound_005 (server * serv, char *word[], const message_tags_data *tags_data)
 			serv->modes_per_line = atoi (word[w] + 6);
 		} else if (strncmp (word[w], "CHANTYPES=", 10) == 0)
 		{
-			free (serv->chantypes);
-			serv->chantypes = strdup (word[w] + 10);
+			g_free (serv->chantypes);
+			serv->chantypes = g_strdup (word[w] + 10);
 		} else if (strncmp (word[w], "CHANMODES=", 10) == 0)
 		{
-			free (serv->chanmodes);
-			serv->chanmodes = strdup (word[w] + 10);
+			g_free (serv->chanmodes);
+			serv->chanmodes = g_strdup (word[w] + 10);
 		} else if (strncmp (word[w], "PREFIX=", 7) == 0)
 		{
 			pre = strchr (word[w] + 7, ')');
 			if (pre)
 			{
 				pre[0] = 0;			  /* NULL out the ')' */
-				free (serv->nick_prefixes);
-				free (serv->nick_modes);
-				serv->nick_prefixes = strdup (pre + 1);
-				serv->nick_modes = strdup (word[w] + 8);
+				g_free (serv->nick_prefixes);
+				g_free (serv->nick_modes);
+				serv->nick_prefixes = g_strdup (pre + 1);
+				serv->nick_modes = g_strdup (word[w] + 8);
 			} else
 			{
 				/* bad! some ircds don't give us the modes. */
 				/* in this case, we use it only to strip /NAMES */
 				serv->bad_prefix = TRUE;
-				if (serv->bad_nick_prefixes)
-					free (serv->bad_nick_prefixes);
-				serv->bad_nick_prefixes = strdup (word[w] + 7);
+				g_free (serv->bad_nick_prefixes);
+				serv->bad_nick_prefixes = g_strdup (word[w] + 7);
 			}
 		} else if (strncmp (word[w], "WATCH=", 6) == 0)
 		{
@@ -832,10 +831,6 @@ inbound_005 (server * serv, char *word[], const message_tags_data *tags_data)
 			serv->supports_monitor = TRUE;
 		} else if (strncmp (word[w], "NETWORK=", 8) == 0)
 		{
-/*			if (serv->networkname)
-				free (serv->networkname);
-			serv->networkname = strdup (word[w] + 8);*/
-
 			if (serv->server_session->type == SESS_SERVER)
 			{
 				safe_strcpy (serv->server_session->channel, word[w] + 8, CHANLEN);
diff --git a/src/common/msproxy.c b/src/common/msproxy.c
deleted file mode 100644
index 5f631c7f..00000000
--- a/src/common/msproxy.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/* X-Chat
- * Copyright (C) 1998 Peter Zelezny.
- *
- * 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
- *
- * MS Proxy (ISA server) support is (c) 2006 Pavel Fedin <sonic_amiga@rambler.ru>
- * based on Dante source code
- * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- *      Inferno Nettverk A/S, Norway.  All rights reserved.
- */
-
-/*#define DEBUG_MSPROXY*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
-#ifndef WIN32
-#include <unistd.h>
-#endif
-
-#define WANTSOCKET
-#define WANTARPA
-#include "inet.h"
-
-#include "hexchat.h"
-#include "network.h"
-#include "hexchatc.h"
-#include "server.h"
-#include "msproxy.h"
-
-
-#ifdef USE_MSPROXY
-#include <ntlm.h>
-
-static int
-send_msprequest(s, state, request, end)
-	int s;
-	struct msproxy_state_t *state;
-	struct msproxy_request_t *request;
-	char *end;
-{
-	ssize_t w;
-	size_t l;
-
-	request->magic25 = htonl(MSPROXY_VERSION);
-	request->serverack = state->seq_recv;
-	/* don't start incrementing sequence until we are acking packet #2. */
-	request->sequence	= (unsigned char)(request->serverack >= 2 ? state->seq_sent + 1 : 0);
-
-	memcpy(request->RWSP, "RWSP", sizeof(request->RWSP));
-
-	l = end - (char *)request;
-	/* all requests must be atleast MSPROXY_MINLENGTH it seems. */
-	if (l < MSPROXY_MINLENGTH) {
-		bzero(end, (size_t)(MSPROXY_MINLENGTH - l));
-		l = MSPROXY_MINLENGTH;
-	}
-
-	if ((w = send(s, request, l, 0)) != l) {
-#ifdef DEBUG_MSPROXY
-		printf ("send_msprequest(): send() failed (%ld bytes sent instead of %Iu\n", w, l);
-		perror ("Error is");
-#endif
-		return -1;
-	}
-	state->seq_sent = request->sequence;
-
-	return w;
-}
-
-static int
-recv_mspresponse(s, state, response)
-	int s;
-	struct msproxy_state_t *state;
-	struct msproxy_response_t *response;
-{
-	ssize_t r;
-
-	do {
-		if ((r = recv (s, response, sizeof (*response), 0)) < MSPROXY_MINLENGTH) {
-#ifdef DEBUG_MSPROXY
-			printf ("recv_mspresponse(): expected to read atleast %d, read %ld\n", MSPROXY_MINLENGTH, r);
-#endif
-			return -1;
-		}
-		if (state->seq_recv == 0)
-			break; /* not started incrementing yet. */
-#ifdef DEBUG_MSPROXY
-		if (response->sequence == state->seq_recv)
-			printf ("seq_recv: %d, dup response, seqnumber: 0x%x\n", state->seq_recv, response->sequence);
-#endif
-	} while (response->sequence == state->seq_recv);
-
-	state->seq_recv = response->sequence;
-
-	return r;
-}
-
-int
-traverse_msproxy (int sok, char *serverAddr, int port, struct msproxy_state_t *state, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound)
-{
-	struct msproxy_request_t req;
-	struct msproxy_response_t res;
-	char *data, *p;
-	char hostname[NT_MAXNAMELEN];
-	char ntdomain[NT_MAXNAMELEN];
-	char challenge[8];
-	netstore *ns_client;
-	int clientport;
-	guint32 destaddr;
-	guint32 flags;
-
-	if (!prefs.hex_net_proxy_auth || !prefs.hex_net_proxy_user[0] || !prefs.hex_net_proxy_pass[0] )
-		return 1;
-
-	/* MS proxy protocol implementation currently doesn't support IPv6 */
-	destaddr = net_getsockaddr_v4 (ns_proxy);
-	if (!destaddr)
-		return 1;
-
-	state->seq_recv = 0;
-	state->seq_sent = 0;
-
-#ifdef DEBUG_MSPROXY
-	printf ("Connecting to %s:%d via MS proxy\n", serverAddr, port);
-#endif
-
-	gethostname (hostname, NT_MAXNAMELEN);
-	p = strchr (hostname, '.');
-        if (p)
-        	*p = '\0';
-
-	bzero (&req, sizeof(req));
-	req.clientid		= htonl(0x0a000000);	/* Initial client ID is always 0x0a		*/
-	req.command		= htons(MSPROXY_HELLO);	/* HELLO command					*/
-	req.packet.hello.magic5	= htons(0x4b00);	/* Fill in magic values				*/
-	req.packet.hello.magic10	= htons(0x1400);
-	req.packet.hello.magic15	= htons(0x0400);
-	req.packet.hello.magic20	= htons(0x5704);
-	req.packet.hello.magic25	= htons(0x0004);
-	req.packet.hello.magic30	= htons(0x0100);
-	req.packet.hello.magic35	= htons(0x4a02);
-	req.packet.hello.magic40	= htons(0x3000);
-	req.packet.hello.magic45	= htons(0x4400);
-	req.packet.hello.magic50	= htons(0x3900);
-	data = req.packet.hello.data;
-	strcpy (data, prefs.hex_net_proxy_user);		/* Append a username				*/
-	data += strlen (prefs.hex_net_proxy_user)+2;		/* +2 automatically creates second empty string	*/
-	strcpy (data, MSPROXY_EXECUTABLE);		/* Append an application name			*/
-	data += strlen (MSPROXY_EXECUTABLE)+1;
-	strcpy (data, hostname);				/* Append a hostname				*/
-	data += strlen (hostname)+1;
-
-	if (send_msprequest(sok, state, &req, data) == -1)
-		return 1;
-
-	if (recv_mspresponse(sok, state, &res) == -1)
-		return 1;
-
-	if (strcmp(res.RWSP, "RWSP") != 0) {
-#ifdef DEBUG_MSPROXY
-		printf ("Received mailformed packet (no RWSP signature)\n");
-#endif
-		return 1;
-	}
-
-	if (ntohs(res.command) >> 8 != 0x10) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.command = 10??, is %x", ntohs(res.command));
-#endif
-		return 1;
-	}
-
-	state->clientid	= htonl(rand());
-	state->serverid	= res.serverid;
-
-#ifdef DEBUG_MSPROXY
-	printf ("clientid: 0x%x, serverid: 0x%0x\n", state->clientid, state->serverid);
-	printf ("packet #2\n");
-#endif
-
-	/* almost identical. */
-	req.clientid	= state->clientid;
-	req.serverid	= state->serverid;
-
-	if (send_msprequest(sok, state, &req, data) == -1)
-		return 1;
-
-	if (recv_mspresponse(sok, state, &res) == -1)
-		return 1;
-
-	if (res.serverid != state->serverid) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected serverid = 0x%x, is 0x%x\n",state->serverid, res.serverid);
-#endif
-		return 1;
-	}
-
-	if (res.sequence != 0x01) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.sequence = 0x01, is 0x%x\n", res.sequence);
-#endif
-		return 1;
-	}
-
-	if (ntohs(res.command) != MSPROXY_USERINFO_ACK) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_USERINFO_ACK, ntohs(res.command));
-#endif
-		return 1;
-	}
-
-#ifdef DEBUG_MSPROXY
-	printf ("packet #3\n");
-#endif
-
-	bzero(&req, sizeof(req));
-	req.clientid			= state->clientid;
-	req.serverid			= state->serverid;
-	req.command			= htons(MSPROXY_AUTHENTICATE);
-	memcpy(req.packet.auth.NTLMSSP, "NTLMSSP", sizeof("NTLMSSP"));
-	req.packet.auth.bindaddr	= htonl(0x02000000);
-	req.packet.auth.msgtype		= htonl(0x01000000);
-	/* NTLM flags:	0x80000000 Negotiate LAN Manager key
-			0x10000000 Negotiate sign
-			0x04000000 Request target
-			0x02000000 Negotiate OEM
-			0x00800000 Always sign
-			0x00020000 Negotiate NTLM
-	*/
-	req.packet.auth.flags		= htonl(0x06020000);
-
-	if (send_msprequest(sok, state, &req, &req.packet.auth.data) == -1)
-		return 1;
-
-	if (recv_mspresponse(sok, state, &res) == -1)
-		return 1;
-
-	if (res.serverid != state->serverid) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected serverid = 0x%x, is 0x%x\n", state->serverid, res.serverid);
-#endif
-		return 1;
-	}
-
-	if (ntohs(res.command) != MSPROXY_AUTHENTICATE_ACK) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_AUTHENTICATE_ACK, ntohs(res.command));
-#endif
-		return 1;
-	}
-
-	flags = res.packet.auth.flags & htonl(0x00020000);			/* Remember if the server supports NTLM */
-	memcpy(challenge, &res.packet.auth.challenge, sizeof(challenge));
-	memcpy(ntdomain, &res.packet.auth.NTLMSSP[res.packet.auth.target.offset], res.packet.auth.target.len);
-	ntdomain[res.packet.auth.target.len] = 0;
-
-#ifdef DEBUG_MSPROXY
-	printf ("ntdomain: \"%s\"\n", ntdomain);
-	printf ("packet #4\n");
-#endif
-
-	bzero(&req, sizeof(req));
-	req.clientid			= state->clientid;
-	req.serverid			= state->serverid;
-	req.command			= htons(MSPROXY_AUTHENTICATE_2);	/* Authentication response			*/
-	req.packet.auth2.magic3		= htons(0x0200);			/* Something					*/
-	memcpy(req.packet.auth2.NTLMSSP, "NTLMSSP", sizeof("NTLMSSP"));		/* Start of NTLM message				*/
-	req.packet.auth2.msgtype		= htonl(0x03000000);			/* Message type 2				*/
-	req.packet.auth2.flags		= flags | htonl(0x02000000);		/* Choose authentication method			*/
-	data = req.packet.auth2.data;
-	if (flags) {
-		req.packet.auth2.lm_resp.len	= 0;				/* We are here if NTLM is supported,		*/
-		req.packet.auth2.lm_resp.alloc	= 0;				/* Do not fill in insecure LM response		*/
-		req.packet.auth2.lm_resp.offset	= data - req.packet.auth2.NTLMSSP;
-		req.packet.auth2.ntlm_resp.len = 24;				/* Fill in NTLM response security buffer	*/
-		req.packet.auth2.ntlm_resp.alloc = 24;
-		req.packet.auth2.ntlm_resp.offset = data - req.packet.auth2.NTLMSSP;
-		ntlm_smb_nt_encrypt(prefs.hex_net_proxy_pass, challenge, data);		/* Append an NTLM response			*/
-		data += 24;	
-	} else {
-		req.packet.auth2.lm_resp.len	= 24;				/* Fill in LM response security buffer		*/
-		req.packet.auth2.lm_resp.alloc	= 24;
-		req.packet.auth2.lm_resp.offset	= data - req.packet.auth2.NTLMSSP;
-		ntlm_smb_encrypt(prefs.hex_net_proxy_pass, challenge, data);		/* Append an LM response			*/
-		data += 24;
-		req.packet.auth2.ntlm_resp.len = 0;				/* NTLM response is empty			*/
-		req.packet.auth2.ntlm_resp.alloc = 0;
-		req.packet.auth2.ntlm_resp.offset = data - req.packet.auth2.NTLMSSP;
-	}
-	req.packet.auth2.ntdomain_buf.len = strlen(ntdomain);			/* Domain name					*/
-	req.packet.auth2.ntdomain_buf.alloc = req.packet.auth2.ntdomain_buf.len;
-	req.packet.auth2.ntdomain_buf.offset = data - req.packet.auth2.NTLMSSP;
-	strcpy(data, ntdomain);
-	data += req.packet.auth2.ntdomain_buf.len;
-	req.packet.auth2.username_buf.len = strlen(prefs.hex_net_proxy_user);		/* Username					*/
-	req.packet.auth2.username_buf.alloc = req.packet.auth2.username_buf.len;
-	req.packet.auth2.username_buf.offset = data - req.packet.auth2.NTLMSSP;
-	strcpy(data, prefs.hex_net_proxy_user);
-	data += req.packet.auth2.username_buf.len;
-	req.packet.auth2.clienthost_buf.len = strlen(hostname);			/* Hostname					*/
-	req.packet.auth2.clienthost_buf.alloc = req.packet.auth2.clienthost_buf.len;
-	req.packet.auth2.clienthost_buf.offset = data - req.packet.auth2.NTLMSSP;
-	strcpy(data, hostname);
-	data += req.packet.auth2.clienthost_buf.len;
-	req.packet.auth2.sessionkey_buf.len = 0;				/* Session key (we don't use it)		*/
-	req.packet.auth2.sessionkey_buf.alloc = 0;
-	req.packet.auth2.sessionkey_buf.offset = data - req.packet.auth2.NTLMSSP;
-
-	if (send_msprequest(sok, state, &req, data) == -1)
-		return 1;
-
-	if (recv_mspresponse(sok, state, &res) == -1)
-		return 1;
-
-	if (res.serverid != state->serverid) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.serverid = 0x%x, is 0x%x\n", state->serverid, res.serverid);
-#endif
-		return 1;
-	}
-
-	if (res.clientack != 0x01) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.clientack = 0x01, is 0x%x\n", res.clientack);
-#endif
-		return 1;
-	}
-
-	if (ntohs(res.command) >> 8 != 0x47) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.command = 47??, is 0x%x\n", ntohs(res.command));
-#endif
-		return 1;
-	}
-
-	if (ntohs(res.command) ==  MSPROXY_AUTHENTICATE_2_NAK) {
-#ifdef DEBUG_MSPROXY
-		printf ("Authentication failed\n");
-#endif
-		return -1;
-	}
-
-#ifdef DEBUG_MSPROXY
-	printf ("packet #5\n");
-#endif
-
-	bzero(&req, sizeof(req));
-	req.clientid			= state->clientid;
-	req.serverid			= state->serverid;
-	req.command			= htons(MSPROXY_CONNECT);
-	req.packet.connect.magic2	= htons(0x0200);
-	req.packet.connect.magic6	= htons(0x0200);
-	req.packet.connect.destport	= htons(port);
-	req.packet.connect.destaddr	= destaddr;
-	data = req.packet.connect.executable;
-	strcpy(data, MSPROXY_EXECUTABLE);
-	data += strlen(MSPROXY_EXECUTABLE) + 1;
-
-	/*
-	 * need to tell server what port we will connect from, so we bind our sockets.
-	 */
-	ns_client = net_store_new ();
-	if (!bound) {
-		net_store_fill_any (ns_client);
-		net_bind(ns_client, csok4, csok6);
-#ifdef DEBUG_MSPROXY
-		perror ("bind() result");
-#endif
-	}
- 	clientport = net_getsockport(csok4, csok6);
-	if (clientport == -1) {
-#ifdef DEBUG_MSPROXY
-		printf ("Unable to obtain source port\n");
-#endif
-		return 1;
-	}
-	req.packet.connect.srcport = clientport;
-
-	if (send_msprequest(sok, state, &req, data) == -1)
-		return 1;
-
-	if (recv_mspresponse(sok, state, &res) == -1)
-		return 1;
-
-	if (ntohs(res.command) != MSPROXY_CONNECT_ACK) {
-#ifdef DEBUG_MSPROXY
-		printf ("expected res.command = 0x%x, is 0x%x\n",MSPROXY_CONNECT_ACK, ntohs(res.command));
-#endif
-		return 1;
-	}
-
-	net_store_fill_v4 (ns_client, res.packet.connect.clientaddr, res.packet.connect.clientport);
-
-#ifdef DEBUG_MSPROXY
-	printf ("Connecting...\n");
-#endif
-	if (net_connect (ns_client, csok4, csok6, csok) != 0) {
-#ifdef DEBUG_MSPROXY
-		printf ("Failed to connect to port %d\n", htons(res.packet.connect.clientport));
-#endif
-		net_store_destroy (ns_client);
-		return 1;
-	}
-	net_store_destroy (ns_client);
-#ifdef DEBUG_MSPROXY
-	printf ("packet #6\n");
-#endif
-
-	req.clientid	= state->clientid;
-	req.serverid	= state->serverid;
-	req.command	= htons(MSPROXY_USERINFO_ACK);		
-
-	if (send_msprequest(sok, state, &req, req.packet.connack.data) == -1)
-		return 1;
-
-	return 0;
-}
-
-void
-msproxy_keepalive (void)
-{
-	server *serv;
-	GSList *list = serv_list;
-	struct msproxy_request_t req;
-	struct msproxy_response_t res;
-
-	while (list)
-	{
-		serv = list->data;
-		if (serv->connected && (serv->proxy_sok != -1))
-		{
-#ifdef DEBUG_MSPROXY
-			printf ("sending MS proxy keepalive packet\n");
-#endif
-
-			bzero(&req, sizeof(req));
-			req.clientid	= serv->msp_state.clientid;
-			req.serverid	= serv->msp_state.serverid;
-			req.command	= htons(MSPROXY_HELLO);
-			
-			if (send_msprequest(serv->proxy_sok, &serv->msp_state, &req, req.packet.hello.data) == -1)
-				continue;
-
-			recv_mspresponse(serv->proxy_sok, &serv->msp_state, &res);
-
-#ifdef DEBUG_MSPROXY
-			if (ntohs(res.command) != MSPROXY_USERINFO_ACK)
-				printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_USERINFO_ACK, ntohs(res.command));
-#endif
-		}
-		list = list->next;
-	}
-}
-
-#endif
diff --git a/src/common/msproxy.h b/src/common/msproxy.h
deleted file mode 100644
index 4371d704..00000000
--- a/src/common/msproxy.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/* X-Chat
- * Copyright (C) 1998 Peter Zelezny.
- *
- * 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
- *
- * MS Proxy (ISA server) support is (c) 2006 Pavel Fedin <sonic_amiga@rambler.ru>
- * based on Dante source code
- * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- *      Inferno Nettverk A/S, Norway.  All rights reserved.
- */
-
-#ifndef HEXCHAT_MSPROXY_H
-#define HEXCHAT_MSPROXY_H
-
-#include "network.h"
-
-#define MSPROXY_EXECUTABLE 		"hexchat.exe"	/* This probably can be used for access control on the server side */
-
-#define MSPROXY_MINLENGTH		172		/* minimum length of packet.				*/
-#define NT_MAXNAMELEN			17		/* maximum name length (domain etc), comes from NetBIOS */
-#define MSPROXY_VERSION			0x00010200	/* MS Proxy v2 ?					*/
-
-/* Commands / responses */
-#define MSPROXY_HELLO			0x0500	/* packet 1 from client.			*/
-#define MSPROXY_HELLO_ACK		0x1000	/* packet 1 from server.			*/
-
-#define MSPROXY_USERINFO_ACK		0x0400	/* packet 2 from server.			*/
-
-#define MSPROXY_AUTHENTICATE		0x4700	/* authentication request		*/
-#define MSPROXY_AUTHENTICATE_ACK	0x4714	/* authentication challenge		*/
-
-#define MSPROXY_AUTHENTICATE_2		0x4701	/* authentication response		*/
-#define MSPROXY_AUTHENTICATE_2_ACK	0x4715	/* authentication passed		*/
-#define MSPROXY_AUTHENTICATE_2_NAK	0x4716	/* authentication failure		*/
-
-#define MSPROXY_CONNECT			0x071e	/* connect request.			*/
-#define MSPROXY_CONNECT_ACK		0x0703	/* connect request accepted.		*/
-
-#pragma pack(1)
-
-struct ntlm_buffer {
-	guint16	len;
-	guint16	alloc;
-	guint32	offset;
-};
-
-struct msproxy_request_t {
-	guint32					clientid;			/* 1-4							*/
-	guint32					magic25;				/* 5-8							*/
-	guint32					serverid;			/* 9-12							*/
-	unsigned char				serverack;			/* 13: ack of last server packet			*/
-	char					pad10[3];			/* 14-16						*/
-	unsigned char				sequence;			/* 17: sequence # of this packet.			*/
-	char					pad11[7];			/* 18-24						*/
-	char					RWSP[4];			/* 25-28: 0x52,0x57,0x53,0x50				*/
-	char					pad15[8];			/* 29-36						*/
-	guint16					command;				/* 37-38						*/
-
-	/* packet specifics start at 39. */
-	union {
-		struct {
-			char			pad1[18];			/* 39-56						*/
-			guint16			magic3;				/* 57-58						*/
-			char           		pad3[114];			/* 59-172						*/
-			guint16			magic5;				/* 173-174: 0x4b, 0x00					*/
-			char			pad5[2];			/* 175-176						*/
-			guint16			magic10;				/* 177-178: 0x14, 0x00					*/
-			char			pad6[2];			/* 179-180						*/
-			guint16			magic15;				/* 181-182: 0x04, 0x00					*/
-			char			pad10[2];			/* 183-184						*/
-			guint16			magic16;				/* 185-186						*/
-			char			pad11[2];			/* 187-188						*/
-			guint16			magic20;				/* 189-190: 0x57, 0x04					*/
-			guint16			magic25;				/* 191-192: 0x00, 0x04					*/
-			guint16			magic30;				/* 193-194: 0x01, 0x00					*/
-			char			pad20[2];			/* 195-196: 0x4a, 0x02					*/
-			guint16			magic35;				/* 197-198: 0x4a, 0x02					*/
-			char			pad30[10];			/* 199-208						*/
-			guint16			magic40;				/* 209-210: 0x30, 0x00					*/
-			char			pad40[2];			/* 211-212						*/
-			guint16			magic45;				/* 213-214: 0x44, 0x00					*/
-			char			pad45[2];			/* 215-216						*/
-			guint16			magic50;				/* 217-218: 0x39, 0x00					*/
-			char			pad50[2];			/* 219-220						*/
-			char			data[256];			/* 221-EOP: a sequence of NULL-terminated strings:
-											- username;
-											- empty string (just a NULL);
-											- application name;
-											- hostname					*/
-		} hello;
-
-		struct {
-			char			pad1[4];			/* 39-42						*/
-			guint16			magic2;				/* 43-44						*/
-			char			pad10[12];			/* 45-56						*/
-			guint32			bindaddr;			/* 57-60: address to bind.				*/
-			guint16			bindport;			/* 61-62: port to bind.					*/
-			char           		pad15[2];			/* 63-64						*/
-			guint16			magic3;				/* 65-66						*/
-			guint16			boundport;			/* 67-68						*/
-			char           		pad20[104];			/* 69-172						*/
-			char			NTLMSSP[sizeof("NTLMSSP")];	/* 173-180: "NTLMSSP"					*/
-			guint32			msgtype;				/* 181-184: NTLM message type = 1			*/
-			guint32			flags;				/* 185-188: NTLM message flags				*/
-			guint16			magic20;				/* 189-190: 0x28, 0x00					*/
-			char			pad30[2];			/* 191-192						*/
-			guint16			magic25;				/* 193-194: 0x96, 0x82					*/
-			guint16			magic30;				/* 195-196: 0x01, 0x00					*/
-			char			pad40[12];			/* 197-208						*/
-			guint16			magic50;				/* 209-210: 0x30, 0x00					*/
-			char			pad50[6];			/* 211-216						*/
-			guint16			magic55;				/* 217-218: 0x30, 0x00					*/
-			char			pad55[2];			/* 219-220						*/
-			char			data[0];			/* Dummy end marker, no real data required		*/
-		} auth;
-
-		struct {
-			char			pad1[4];			/* 39-42						*/
-			guint16			magic1;				/* 43-44						*/
-			guint32			magic2;				/* 45-48						*/
-			char			pad2[8];			/* 49-56						*/
-			guint16			magic3;				/* 57-58						*/
-			char			pad3[6];			/* 59-64						*/
-			guint16			magic4;				/* 65-66						*/
-			guint16			boundport;			/* 67-68						*/
-			char           		pad4[104];			/* 69-172						*/
-			char			NTLMSSP[sizeof("NTLMSSP")];	/* 173-180: "NTLMSSP"					*/
-			guint32			msgtype;				/* 181-184: NTLM message type = 3			*/
-			struct ntlm_buffer	lm_resp;				/* 185-192: LM response security buffer			*/
-			struct ntlm_buffer	ntlm_resp;			/* 193-200: NTLM response security buffer		*/
-			struct ntlm_buffer	ntdomain_buf;			/* 201-208: domain name security buffer			*/
-			struct ntlm_buffer	username_buf;			/* 209-216: username security buffer			*/
-			struct ntlm_buffer	clienthost_buf;			/* 217-224: hostname security buffer			*/
-			struct ntlm_buffer	sessionkey_buf;			/* 225-232: session key security buffer			*/
-			guint32			flags;				/* 233-236: message flags				*/
-			char			data[1024];			/* 237-EOP: data area					*/
-		} auth2;
-
-		struct {
-			guint16			magic1;				/* 39-40						*/
-			char			pad1[2];			/* 41-42						*/
-			guint16			magic2;				/* 43-44						*/
-			guint32			magic3;				/* 45-48						*/
-			char			pad5[8];			/* 48-56						*/
-			guint16			magic6;				/* 57-58: 0x0200					*/
-			guint16			destport;			/* 59-60						*/
-			guint32			destaddr;			/* 61-64						*/
-			char			pad10[4];			/* 65-68						*/
-			guint16			magic10;				/* 69-70						*/
-			char			pad15[2];			/* 71-72						*/
-			guint16			srcport;			/* 73-74: port client connects from			*/
-			char			pad20[82];			/* 75-156						*/
-			char			executable[256];		/* 76-EOP: application name				*/
-		} connect;
-
-		struct {
-			guint16			magic1;				/* 39-40						*/
-			char			pad5[2];			/* 41-42						*/
-			guint16			magic5;				/* 43-44						*/
-			guint32			magic10;				/* 45-48						*/
-			char			pad10[2];			/* 49-50						*/
-			guint16			magic15;				/* 51-52						*/
-			guint32			magic16;				/* 53-56						*/
-			guint16			magic20;				/* 57-58						*/
-			guint16			clientport;			/* 59-60: forwarded port.				*/
-			guint32			clientaddr;			/* 61-64: forwarded address.				*/
-			guint32			magic30;				/* 65-68						*/
-			guint32			magic35;				/* 69-72						*/
-			guint16			serverport;			/* 73-74: port server will connect to us from.		*/
-			guint16			srcport;			/* 75-76: connect request; port used on client behalf.	*/
-			guint16			boundport;			/* 77-78: bind request; port used on client behalf.	*/
-			guint32			boundaddr;			/* 79-82: addr used on client behalf			*/
-			char			pad30[90];			/* 83-172						*/
-			char			data[0];			/* End marker						*/
-		} connack;
-
-	} packet;
-};
-
-struct msproxy_response_t {
-	guint32					packetid;			/* 1-4							*/
-	guint32					magic5;				/* 5-8							*/
-	guint32             			serverid;			/* 9-12							*/
-	char					clientack;			/* 13: ack of last client packet.			*/
-	char					pad5[3];			/* 14-16						*/
-	unsigned char				sequence;			/* 17: sequence # of this packet.			*/
-	char					pad10[7];			/* 18-24						*/
-	char					RWSP[4];			/* 25-28: 0x52,0x57,0x53,0x50				*/
-	char					pad15[8];			/* 29-36						*/
-	guint16					command;				/* 37-38						*/
-
-	union {
-		struct {
-			char			pad5[18];			/* 39-56						*/
-			guint16			magic20;				/* 57-58: 0x02, 0x00					*/
-			char			pad10[6];			/* 59-64						*/
-			guint16			magic30;				/* 65-66: 0x74, 0x01					*/
-			char			pad15[2];			/* 67-68						*/
-			guint16			magic35;				/* 69-70: 0x0c, 0x00					*/
-			char			pad20[6];			/* 71-76						*/
-			guint16			magic50;				/* 77-78: 0x04, 0x00					*/
-			char			pad30[6];			/* 79-84						*/
-			guint16			magic60;				/* 85-86: 0x65, 0x05					*/
-			char			pad35[2];			/* 87-88						*/
-			guint16			magic65;				/* 89-90: 0x02, 0x00					*/
-			char			pad40[8];			/* 91-98						*/
-			guint16			udpport;			/* 99-100						*/
-			guint32			udpaddr;			/* 101-104						*/
-		} hello;
-
-		struct {
-			char			pad1[6];			/* 39-44						*/
-			guint32			magic10;				/* 45-48						*/
-			char			pad3[10];			/* 49-58						*/
-			guint16			boundport;			/* 59-60: port server bound for us.			*/
-			guint32			boundaddr;			/* 61-64: addr server bound for us.			*/
-			char			pad10[4];			/* 65-68						*/
-			guint16			magic15;				/* 69-70						*/
-			char			pad15[102];			/* 70-172						*/
-			char			NTLMSSP[sizeof("NTLMSSP")];	/* 173-180: "NTLMSSP"					*/
-			guint32			msgtype;				/* 181-184: NTLM message type = 2			*/
-			struct ntlm_buffer	target;				/* 185-192: target security buffer			*/
-			guint32			flags;				/* 193-196: NTLM message flags				*/
-			char			challenge[8];			/* 197-204: NTLM challenge request			*/
-			char			context[8];			/* 205-212: NTLM context				*/
-			char			data[1024];			/* 213-EOP: target information data			*/
-		} auth;
-
-		struct {
-			guint16			magic1;				/* 39-40						*/
-			char			pad5[18];			/* 41-58						*/
-			guint16			clientport;			/* 59-60: forwarded port.				*/
-			guint32			clientaddr;			/* 61-64: forwarded address.				*/
-			guint32			magic10;				/* 65-68						*/
-			guint32			magic15;				/* 69-72						*/
-			guint16			serverport;			/* 73-74: port server will connect to us from.		*/
-			guint16			srcport;			/* 75-76: connect request; port used on client behalf.	*/
-			guint16			boundport;			/* 77-78: bind request; port used on client behalf.	*/
-			guint32			boundaddr;			/* 79-82: addr used on client behalf			*/
-			char			pad10[90];			/* 83-172						*/
-		} connect;
-	} packet;
-};
-
-#pragma pack()
-
-int traverse_msproxy (int sok, char *serverAddr, int port, struct msproxy_state_t *state, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound);
-void msproxy_keepalive (void);
-
-#endif
diff --git a/src/common/network.c b/src/common/network.c
index 8790f673..fcdaf547 100644
--- a/src/common/network.c
+++ b/src/common/network.c
@@ -18,6 +18,8 @@
 
 /* ipv4 and ipv6 networking functions with a common interface */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -26,7 +28,6 @@
 #ifndef WIN32
 #include <unistd.h>
 #endif
-#include "../../config.h"
 
 #define WANTSOCKET
 #define WANTARPA
@@ -64,128 +65,17 @@ net_ip (guint32 addr)
 void
 net_store_destroy (netstore * ns)
 {
-#ifdef USE_IPV6
 	if (ns->ip6_hostent)
 		freeaddrinfo (ns->ip6_hostent);
-#endif
-	free (ns);
+	g_free (ns);
 }
 
 netstore *
 net_store_new (void)
 {
-	netstore *ns;
-
-	ns = malloc (sizeof (netstore));
-	memset (ns, 0, sizeof (netstore));
-
-	return ns;
-}
-
-#ifndef USE_IPV6
-
-/* =================== IPV4 ================== */
-
-/*
-	A note about net_resolve and lookupd:
-
-	Many IRC networks rely on round-robin DNS for load balancing, rotating the list
-	of IP address on each query. However, this method breaks when DNS queries are
-	cached. Mac OS X and Darwin handle DNS lookups through the lookupd daemon, which
-	caches queries in its default configuration: thus, if we always pick the first
-	address, we will be stuck with the same host (which might be down!) until the
-	TTL reaches 0 or lookupd is reset (typically, at reboot). Therefore, we need to
-	pick a random address from the result list, instead of always using the first.
-*/
-
-char *
-net_resolve (netstore * ns, char *hostname, int port, char **real_host)
-{
-	ns->ip4_hostent = gethostbyname (hostname);
-	if (!ns->ip4_hostent)
-		return NULL;
-
-	memset (&ns->addr, 0, sizeof (ns->addr));
-#ifdef LOOKUPD
-	int count = 0;
-	while (ns->ip4_hostent->h_addr_list[count]) count++;
-	memcpy (&ns->addr.sin_addr,
-			ns->ip4_hostent->h_addr_list[RAND_INT(count)],
-			ns->ip4_hostent->h_length);
-#else
-	memcpy (&ns->addr.sin_addr, ns->ip4_hostent->h_addr,
-			  ns->ip4_hostent->h_length);
-#endif
-	ns->addr.sin_port = htons (port);
-	ns->addr.sin_family = AF_INET;
-
-	*real_host = strdup (ns->ip4_hostent->h_name);
-	return strdup (inet_ntoa (ns->addr.sin_addr));
-}
-
-int
-net_connect (netstore * ns, int sok4, int sok6, int *sok_return)
-{
-	*sok_return = sok4;
-	return connect (sok4, (struct sockaddr *) &ns->addr, sizeof (ns->addr));
-}
-
-void
-net_bind (netstore * tobindto, int sok4, int sok6)
-{
-	bind (sok4, (struct sockaddr *) &tobindto->addr, sizeof (tobindto->addr));
-}
-
-void
-net_sockets (int *sok4, int *sok6)
-{
-	*sok4 = socket (AF_INET, SOCK_STREAM, 0);
-	*sok6 = -1;
-	net_set_socket_options (*sok4);
-}
-
-void
-udp_sockets (int *sok4, int *sok6)
-{
-	*sok4 = socket (AF_INET, SOCK_DGRAM, 0);
-	*sok6 = -1;
-}
-
-void
-net_store_fill_any (netstore *ns)
-{
-	ns->addr.sin_family = AF_INET;
-	ns->addr.sin_addr.s_addr = INADDR_ANY;
-	ns->addr.sin_port = 0;
-}
-
-void
-net_store_fill_v4 (netstore *ns, guint32 addr, int port)
-{
-	ns->addr.sin_family = AF_INET;
-	ns->addr.sin_addr.s_addr = addr;
-	ns->addr.sin_port = port;
+	return g_new0 (netstore, 1);
 }
 
-guint32
-net_getsockaddr_v4 (netstore *ns)
-{
-	return ns->addr.sin_addr.s_addr;
-}
-
-int
-net_getsockport (int sok4, int sok6)
-{
-	struct sockaddr_in addr;
-	int len = sizeof (addr);
-
-	if (getsockname (sok4, (struct sockaddr *)&addr, &len) == -1)
-		return -1;
-	return addr.sin_port;
-}
-
-#else
-
 /* =================== IPV6 ================== */
 
 char *
@@ -231,11 +121,11 @@ net_resolve (netstore * ns, char *hostname, int port, char **real_host)
 					 ipstring, sizeof (ipstring), NULL, 0, NI_NUMERICHOST);
 
 	if (ns->ip6_hostent->ai_canonname)
-		*real_host = strdup (ns->ip6_hostent->ai_canonname);
+		*real_host = g_strdup (ns->ip6_hostent->ai_canonname);
 	else
-		*real_host = strdup (hostname);
+		*real_host = g_strdup (hostname);
 
-	return strdup (ipstring);
+	return g_strdup (ipstring);
 }
 
 /* the only thing making this interface unclean, this shitty sok4, sok6 business */
@@ -298,88 +188,3 @@ udp_sockets (int *sok4, int *sok6)
 	*sok4 = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 	*sok6 = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
 }
-
-/* the following functions are used only by MSPROXY and are not
-   proper ipv6 implementations - do not use in new code! */
-
-void
-net_store_fill_any (netstore *ns)
-{
-	struct addrinfo *ai;
-	struct sockaddr_in *sin;
-
-	ai = ns->ip6_hostent;
-	if (!ai) {
-		ai = malloc (sizeof (struct addrinfo));
-		memset (ai, 0, sizeof (struct addrinfo));
-		ns->ip6_hostent = ai;
-	}
-	sin = (struct sockaddr_in *)ai->ai_addr;
-	if (!sin) {
-		sin = malloc (sizeof (struct sockaddr_in));
-		memset (sin, 0, sizeof (struct sockaddr_in));
-		ai->ai_addr = (struct sockaddr *)sin;
-	}
-	ai->ai_family = AF_INET;
-	ai->ai_addrlen = sizeof(struct sockaddr_in);
-	sin->sin_family = AF_INET;
-	sin->sin_addr.s_addr = INADDR_ANY;
-	sin->sin_port = 0;
-	ai->ai_next = NULL;
-}
-
-void
-net_store_fill_v4 (netstore *ns, guint32 addr, int port)
-{
-	struct addrinfo *ai;
-	struct sockaddr_in *sin;
-
-	ai = ns->ip6_hostent;
-	if (!ai) {
-		ai = malloc (sizeof (struct addrinfo));
-		memset (ai, 0, sizeof (struct addrinfo));
-		ns->ip6_hostent = ai;
-	}
-	sin = (struct sockaddr_in *)ai->ai_addr;
-	if (!sin) {
-		sin = malloc (sizeof (struct sockaddr_in));
-		memset (sin, 0, sizeof (struct sockaddr_in));
-		ai->ai_addr = (struct sockaddr *)sin;
-	}
-	ai->ai_family = AF_INET;
-	ai->ai_addrlen = sizeof(struct sockaddr_in);
-	sin->sin_family = AF_INET;
-	sin->sin_addr.s_addr = addr;
-	sin->sin_port = port;
-	ai->ai_next = NULL;
-}
-
-guint32
-net_getsockaddr_v4 (netstore *ns)
-{
-	struct addrinfo *ai;
-	struct sockaddr_in *sin;
-
-	ai = ns->ip6_hostent;
-
-	while (ai->ai_family != AF_INET) {
-		ai = ai->ai_next;
-		if (!ai)
-			return 0;
-	}
-	sin = (struct sockaddr_in *)ai->ai_addr;
-	return sin->sin_addr.s_addr;
-}
-
-int
-net_getsockport (int sok4, int sok6)
-{
-	struct sockaddr_in addr;
-	int len = sizeof (addr);
-
-	if (getsockname (sok4, (struct sockaddr *)&addr, &len) == -1)
-		return -1;
-	return addr.sin_port;
-}
-
-#endif
diff --git a/src/common/network.h b/src/common/network.h
index 6a4dce39..8c1c0c79 100644
--- a/src/common/network.h
+++ b/src/common/network.h
@@ -23,13 +23,8 @@
 typedef struct netstore_
 {
 #ifdef NETWORK_PRIVATE
-#ifdef USE_IPV6
 	struct addrinfo *ip6_hostent;
 #else
-	struct hostent *ip4_hostent;
-	struct sockaddr_in addr;
-#endif
-#else
 	int _dummy;	/* some compilers don't like empty structs */
 #endif
 } netstore;
@@ -43,11 +38,5 @@ char *net_resolve (netstore *ns, char *hostname, int port, char **real_host);
 void net_bind (netstore *tobindto, int sok4, int sok6);
 char *net_ip (guint32 addr);
 void net_sockets (int *sok4, int *sok6);
-/* functions for MSPROXY only! */
-void udp_sockets (int *sok4, int *sok6);
-void net_store_fill_any (netstore *ns);
-void net_store_fill_v4 (netstore *ns, guint32 addr, int port);
-guint32 net_getsockaddr_v4 (netstore *ns);
-int net_getsockport(int sok4, int sok6);
 
 #endif
diff --git a/src/common/notify.c b/src/common/notify.c
index bf80a1b5..b5316c36 100644
--- a/src/common/notify.c
+++ b/src/common/notify.c
@@ -47,7 +47,7 @@ int notify_tag = 0;
 static char *
 despacify_dup (char *str)
 {
-	char *p, *res = malloc (strlen (str) + 1);
+	char *p, *res = g_malloc (strlen (str) + 1);
 
 	p = res;
 	while (1)
@@ -70,11 +70,11 @@ notify_netcmp (char *str, void *serv)
 
 	if (rfc_casecmp (str, net) == 0)
 	{
-		free (net);
+		g_free (net);
 		return 0;	/* finish & return FALSE from token_foreach() */
 	}
 
-	free (net);
+	g_free (net);
 	return 1;	/* keep going... */
 }
 
@@ -111,14 +111,10 @@ notify_find_server_entry (struct notify *notify, struct server *serv)
 	if (!notify_do_network (notify, serv))
 		return NULL;
 
-	servnot = malloc (sizeof (struct notify_per_server));
-	if (servnot)
-	{
-		memset (servnot, 0, sizeof (struct notify_per_server));
-		servnot->server = serv;
-		servnot->notify = notify;
-		notify->server_list = g_slist_prepend (notify->server_list, servnot);
-	}
+	servnot = g_new0 (struct notify_per_server, 1);
+	servnot->server = serv;
+	servnot->notify = notify;
+	notify->server_list = g_slist_prepend (notify->server_list, servnot);
 	return servnot;
 }
 
@@ -200,7 +196,7 @@ notify_find (server *serv, char *nick)
 		list = list->next;
 	}
 
-	return 0;
+	return NULL;
 }
 
 static void
@@ -247,10 +243,9 @@ notify_announce_online (server * serv, struct notify_per_server *servnot,
 
 	    /* Let's do whois with idle time (like in /quote WHOIS %s %s) */
 
-	    char *wii_str = malloc (strlen (nick) * 2 + 2);
-	    sprintf (wii_str, "%s %s", nick, nick);
+	    char *wii_str = g_strdup_printf ("%s %s", nick, nick);
 	    serv->p_whois (serv, wii_str);
-	    free (wii_str);
+	    g_free (wii_str);
 	}
 }
 
@@ -346,9 +341,9 @@ notify_watch (server * serv, char *nick, int add)
 		addchar = '-';
 
 	if (serv->supports_monitor)
-		snprintf (tbuf, sizeof (tbuf), "MONITOR %c %s", addchar, nick);
+		g_snprintf (tbuf, sizeof (tbuf), "MONITOR %c %s", addchar, nick);
 	else if (serv->supports_watch)
-		snprintf (tbuf, sizeof (tbuf), "WATCH %c%s", addchar, nick);
+		g_snprintf (tbuf, sizeof (tbuf), "WATCH %c%s", addchar, nick);
 	else
 		return;
 
@@ -561,9 +556,9 @@ notify_showlist (struct session *sess, const message_tags_data *tags_data)
 		notify = (struct notify *) list->data;
 		servnot = notify_find_server_entry (notify, sess->server);
 		if (servnot && servnot->ison)
-			snprintf (outbuf, sizeof (outbuf), _("  %-20s online\n"), notify->name);
+			g_snprintf (outbuf, sizeof (outbuf), _("  %-20s online\n"), notify->name);
 		else
-			snprintf (outbuf, sizeof (outbuf), _("  %-20s offline\n"), notify->name);
+			g_snprintf (outbuf, sizeof (outbuf), _("  %-20s offline\n"), notify->name);
 		PrintTextTimeStamp (sess, outbuf, tags_data->timestamp);
 		list = list->next;
 	}
@@ -596,14 +591,13 @@ notify_deluser (char *name)
 				servnot = (struct notify_per_server *) notify->server_list->data;
 				notify->server_list =
 					g_slist_remove (notify->server_list, servnot);
-				free (servnot);
+				g_free (servnot);
 			}
 			notify_list = g_slist_remove (notify_list, notify);
 			notify_watch_all (notify, FALSE);
-			if (notify->networks)
-				free (notify->networks);
-			free (notify->name);
-			free (notify);
+			g_free (notify->networks);
+			g_free (notify->name);
+			g_free (notify);
 			fe_notify_update (0);
 			return 1;
 		}
@@ -615,27 +609,18 @@ notify_deluser (char *name)
 void
 notify_adduser (char *name, char *networks)
 {
-	struct notify *notify = malloc (sizeof (struct notify));
-	if (notify)
-	{
-		memset (notify, 0, sizeof (struct notify));
-		if (strlen (name) >= NICKLEN)
-		{
-			notify->name = malloc (NICKLEN);
-			safe_strcpy (notify->name, name, NICKLEN);
-		} else
-		{
-			notify->name = strdup (name);
-		}
-		if (networks)
-			notify->networks = despacify_dup (networks);
-		notify->server_list = 0;
-		notify_list = g_slist_prepend (notify_list, notify);
-		notify_checklist ();
-		fe_notify_update (notify->name);
-		fe_notify_update (0);
-		notify_watch_all (notify, TRUE);
-	}
+	struct notify *notify = g_new0 (struct notify, 1);
+
+	notify->name = g_strndup (name, NICKLEN - 1);
+
+	if (networks != NULL)
+		notify->networks = despacify_dup (networks);
+	notify->server_list = 0;
+	notify_list = g_slist_prepend (notify_list, notify);
+	notify_checklist ();
+	fe_notify_update (notify->name);
+	fe_notify_update (0);
+	notify_watch_all (notify, TRUE);
 }
 
 gboolean
@@ -714,7 +699,7 @@ notify_cleanup ()
 			{
 				notify->server_list =
 					g_slist_remove (notify->server_list, servnot);
-				free (servnot);
+				g_free (servnot);
 				nslist = notify->server_list;
 			} else
 			{
diff --git a/src/common/outbound.c b/src/common/outbound.c
index 651558ce..a4611927 100644
--- a/src/common/outbound.c
+++ b/src/common/outbound.c
@@ -90,7 +90,7 @@ random_line (char *file_name)
 	{
 	 nofile:
 		/* reason is not a file, an actual reason! */
-		return strdup (file_name);
+		return g_strdup (file_name);
 	}
 
 	/* count number of lines in file */
@@ -111,7 +111,7 @@ random_line (char *file_name)
 	}
 	while (lines > ran);
 	fclose (fh);
-	return strdup (buf);
+	return g_strdup (buf);
 }
 
 void
@@ -121,7 +121,7 @@ server_sendpart (server * serv, char *channel, char *reason)
 	{
 		reason = random_line (prefs.hex_irc_part_reason);
 		serv->p_part (serv, channel, reason);
-		free (reason);
+		g_free (reason);
 	} else
 	{
 		/* reason set by /quit, /close argument */
@@ -136,12 +136,12 @@ server_sendquit (session * sess)
 
 	if (!sess->quitreason)
 	{
-		colrea = strdup (prefs.hex_irc_quit_reason);
+		colrea = g_strdup (prefs.hex_irc_quit_reason);
 		check_special_chars (colrea, FALSE);
 		rea = random_line (colrea);
-		free (colrea);
+		g_free (colrea);
 		sess->server->p_quit (sess->server, rea);
-		free (rea);
+		g_free (rea);
 	} else
 	{
 		/* reason set by /quit, /close argument */
@@ -269,7 +269,7 @@ cmd_addserver (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		if (!network)
 		{
 			network = servlist_net_add (word[2], "", TRUE);
-			network->encoding = strdup (IRC_DEFAULT_CHARSET);
+			network->encoding = g_strdup (IRC_DEFAULT_CHARSET);
 		}
 		/* if we had the network already, check if the given server already exists */
 		else if (servlist_server_find (network, word_eol[3], NULL))
@@ -379,11 +379,10 @@ cmd_away (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 
 	if (sess->server->last_away_reason != reason)
 	{
-		if (sess->server->last_away_reason)
-			free (sess->server->last_away_reason);
+		g_free (sess->server->last_away_reason);
 
 		if (reason == word_eol[2])
-			sess->server->last_away_reason = strdup (reason);
+			sess->server->last_away_reason = g_strdup (reason);
 		else
 			sess->server->last_away_reason = reason;
 	}
@@ -406,8 +405,7 @@ cmd_back (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		PrintText (sess, _("Already marked back.\n"));
 	}
 
-	if (sess->server->last_away_reason)
-		free (sess->server->last_away_reason);
+	g_free (sess->server->last_away_reason);
 	sess->server->last_away_reason = NULL;
 
 	return TRUE;
@@ -483,19 +481,19 @@ create_mask (session * sess, char *mask, char *mode, char *typestr, int deop)
 			switch (type)
 			{
 			case 0:
-				snprintf (buf, sizeof (buf), "%s %s *!*@%s.*", mode, p2, domain);
+				g_snprintf (buf, sizeof (buf), "%s %s *!*@%s.*", mode, p2, domain);
 				break;
 
 			case 1:
-				snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost);
+				g_snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost);
 				break;
 
 			case 2:
-				snprintf (buf, sizeof (buf), "%s %s *!%s@%s.*", mode, p2, username, domain);
+				g_snprintf (buf, sizeof (buf), "%s %s *!%s@%s.*", mode, p2, username, domain);
 				break;
 
 			case 3:
-				snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost);
+				g_snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost);
 				break;
 			}
 		} else
@@ -503,26 +501,26 @@ create_mask (session * sess, char *mask, char *mode, char *typestr, int deop)
 			switch (type)
 			{
 			case 0:
-				snprintf (buf, sizeof (buf), "%s %s *!*@*%s", mode, p2, domain);
+				g_snprintf (buf, sizeof (buf), "%s %s *!*@*%s", mode, p2, domain);
 				break;
 
 			case 1:
-				snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost);
+				g_snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost);
 				break;
 
 			case 2:
-				snprintf (buf, sizeof (buf), "%s %s *!%s@*%s", mode, p2, username, domain);
+				g_snprintf (buf, sizeof (buf), "%s %s *!%s@*%s", mode, p2, username, domain);
 				break;
 
 			case 3:
-				snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost);
+				g_snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost);
 				break;
 			}
 		}
 
 	} else
 	{
-		snprintf (buf, sizeof (buf), "%s %s", mode, mask);
+		g_snprintf (buf, sizeof (buf), "%s %s", mode, mask);
 	}
 	
 	return g_strdup (buf);
@@ -592,7 +590,6 @@ static int
 cmd_charset (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
 	server *serv = sess->server;
-	const char *locale = NULL;
 	int offset = 0;
 
 	if (strcmp (word[2], "-quiet") == 0)
@@ -600,9 +597,7 @@ cmd_charset (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 
 	if (!word[2 + offset][0])
 	{
-		g_get_charset (&locale);
-		PrintTextf (sess, "Current charset: %s\n",
-						serv->encoding ? serv->encoding : locale);
+		PrintTextf (sess, "Current charset: %s\n", serv->encoding);
 		return TRUE;
 	}
 
@@ -1002,14 +997,14 @@ mdehop_cb (struct User *user, multidata *data)
 static int
 cmd_mdehop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	char **nicks = malloc (sizeof (char *) * sess->hops);
+	char **nicks = g_new0 (char *, sess->hops);
 	multidata data;
 
 	data.nicks = nicks;
 	data.i = 0;
 	tree_foreach (sess->usertree, (tree_traverse_func *)mdehop_cb, &data);
 	send_channel_modes (sess, tbuf, nicks, 0, data.i, '-', 'h', 0);
-	free (nicks);
+	g_free (nicks);
 
 	return TRUE;
 }
@@ -1028,14 +1023,14 @@ mdeop_cb (struct User *user, multidata *data)
 static int
 cmd_mdeop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	char **nicks = malloc (sizeof (char *) * sess->ops);
+	char **nicks = g_new0(char *, sess->ops);
 	multidata data;
 
 	data.nicks = nicks;
 	data.i = 0;
 	tree_foreach (sess->usertree, (tree_traverse_func *)mdeop_cb, &data);
 	send_channel_modes (sess, tbuf, nicks, 0, data.i, '-', 'o', 0);
-	free (nicks);
+	g_free (nicks);
 
 	return TRUE;
 }
@@ -1045,18 +1040,13 @@ GSList *menu_list = NULL;
 static void
 menu_free (menu_entry *me)
 {
-	free (me->path);
-	if (me->label)
-		free (me->label);
-	if (me->cmd)
-		free (me->cmd);
-	if (me->ucmd)
-		free (me->ucmd);
-	if (me->group)
-		free (me->group);
-	if (me->icon)
-		free (me->icon);
-	free (me);
+	g_free (me->path);
+	g_free (me->label);
+	g_free (me->cmd);
+	g_free (me->ucmd);
+	g_free (me->group);
+	g_free (me->icon);
+	g_free (me);
 }
 
 /* strings equal? but ignore underscores */
@@ -1115,9 +1105,9 @@ menu_del_children (char *path, char *label)
 	if (!label)
 		label = "";
 	if (path[0])
-		snprintf (buf, sizeof (buf), "%s/%s", path, label);
+		g_snprintf (buf, sizeof (buf), "%s/%s", path, label);
 	else
-		snprintf (buf, sizeof (buf), "%s", label);
+		g_snprintf (buf, sizeof (buf), "%s", label);
 
 	list = menu_list;
 	while (list)
@@ -1168,7 +1158,9 @@ menu_is_mainmenu_root (char *path, gint16 *offset)
 	{
 		if (!strncmp (path, menus[i] + 1, menus[i][0]))
 		{
-			*offset = menus[i][0] + 1;	/* number of bytes to offset the root */
+			*offset = menus[i][0];	/* number of bytes to offset the root */
+			if (path[*offset] != '\0')
+				*offset += 1;
 			return 0;	/* is not main menu */
 		}
 	}
@@ -1193,7 +1185,7 @@ menu_add (char *path, char *label, char *cmd, char *ucmd, int pos, int state, in
 		return;
 	}
 
-	me = malloc (sizeof (menu_entry));
+	me = g_new (menu_entry, 1);
 	me->pos = pos;
 	me->modifier = mod;
 	me->is_main = menu_is_mainmenu_root (path, &me->root_offset);
@@ -1201,31 +1193,26 @@ menu_add (char *path, char *label, char *cmd, char *ucmd, int pos, int state, in
 	me->markup = markup;
 	me->enable = enable;
 	me->key = key;
-	me->path = strdup (path);
+	me->path = g_strdup (path);
 	me->label = NULL;
 	me->cmd = NULL;
 	me->ucmd = NULL;
 	me->group = NULL;
 	me->icon = NULL;
 
-	if (label)
-		me->label = strdup (label);
-	if (cmd)
-		me->cmd = strdup (cmd);
-	if (ucmd)
-		me->ucmd = strdup (ucmd);
-	if (group)
-		me->group = strdup (group);
-	if (icon)
-		me->icon = strdup (icon);
+	me->label = g_strdup (label);
+	me->cmd = g_strdup (cmd);
+	me->ucmd = g_strdup (ucmd);
+	me->group = g_strdup (group);
+	me->icon = g_strdup (icon);
 
 	menu_list = g_slist_append (menu_list, me);
 	label = fe_menu_add (me);
 	if (label)
 	{
 		/* FE has given us a stripped label */
-		free (me->label);
-		me->label = strdup (label);
+		g_free (me->label);
+		me->label = g_strdup (label);
 		g_free (label); /* this is from pango */
 	}
 }
@@ -1321,7 +1308,7 @@ cmd_menu (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (markup)
 	{
 		char *p;	/* to force pango closing tags through */
-		for (p = label; *p; p++)
+		for (p = label; p && *p; p++)
 			if (*p == 3)
 				*p = '/';
 	}
@@ -1454,7 +1441,7 @@ exec_check_process (struct session *sess)
 	{
 		close (sess->running_exec->myfd);
 		fe_input_remove (sess->running_exec->iotag);
-		free (sess->running_exec);
+		g_free (sess->running_exec);
 		sess->running_exec = NULL;
 	}
 }
@@ -1531,11 +1518,10 @@ cmd_execw (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		return FALSE;
 	}
 	len = strlen(word_eol[2]);
-	temp = malloc(len + 2);
-	sprintf(temp, "%s\n", word_eol[2]);
+	temp = g_strconcat (word_eol[2], "\n", NULL);
 	PrintText(sess, temp);
 	write(sess->running_exec->myfd, temp, len + 1);
-	free(temp);
+	g_free(temp);
 
 	return TRUE;
 }
@@ -1559,7 +1545,7 @@ exec_handle_colors (char *buf, int len)
 	if (strchr (buf, 27) == 0)
 		return;
 
-	nbuf = malloc (len + 1);
+	nbuf = g_malloc (len + 1);
 
 	while (i < len)
 	{
@@ -1653,7 +1639,7 @@ norm:			nbuf[j] = buf[i];
 
 	nbuf[j] = 0;
 	memcpy (buf, nbuf, j + 1);
-	free (nbuf);
+	g_free (nbuf);
 }
 
 #ifndef HAVE_MEMRCHR
@@ -1665,7 +1651,7 @@ memrchr (const void *block, int c, size_t size)
 	for (p = (unsigned char *)block + size; p != block; p--)
 		if (*p == c)
 			return p;
-	return 0;
+	return NULL;
 }
 #endif
 
@@ -1679,14 +1665,14 @@ exec_data (GIOChannel *source, GIOCondition condition, struct nbexec *s)
 	len = s->buffill;
 	if (len) {
 		/* append new data to buffered incomplete line */
-		buf = malloc(len + 2050);
+		buf = g_malloc (len + 2050);
 		memcpy(buf, s->linebuf, len);
 		readpos = buf + len;
-		free(s->linebuf);
+		g_free (s->linebuf);
 		s->linebuf = NULL;
 	}
 	else
-		readpos = buf = malloc(2050);
+		readpos = buf = g_malloc (2050);
 
 	rd = read (sok, readpos, 2048);
 	if (rd < 1)
@@ -1707,12 +1693,12 @@ exec_data (GIOChannel *source, GIOCondition condition, struct nbexec *s)
 			else
 				PrintText (s->sess, buf);
 		}
-		free(buf);
+		g_free(buf);
 		waitpid (s->childpid, NULL, 0);
 		s->sess->running_exec = NULL;
 		fe_input_remove (s->iotag);
 		close (sok);
-		free (s);
+		g_free (s);
 		return TRUE;
 	}
 	len += rd;
@@ -1725,7 +1711,7 @@ exec_data (GIOChannel *source, GIOCondition condition, struct nbexec *s)
 		rest = buf;
 	if (*rest) {
 		s->buffill = len - (rest - buf); /* = strlen(rest) */
-		s->linebuf = malloc(s->buffill + 1);
+		s->linebuf = g_malloc (s->buffill + 1);
 		memcpy(s->linebuf, rest, s->buffill);
 		*rest = '\0';
 		len -= s->buffill; /* possibly 0 */
@@ -1741,7 +1727,7 @@ exec_data (GIOChannel *source, GIOCondition condition, struct nbexec *s)
 			PrintText (s->sess, buf);
 	}
 
-	free(buf);
+	g_free (buf);
 	return TRUE;
 }
 
@@ -1803,8 +1789,7 @@ cmd_exec (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			return FALSE;
 		}
 #endif
-		s = (struct nbexec *) malloc (sizeof (struct nbexec));
-		memset(s, 0, sizeof(*s));
+		s = g_new0 (struct nbexec, 1);
 		s->myfd = fds[0];
 		s->tochannel = tochannel;
 		s->sess = sess;
@@ -1851,8 +1836,9 @@ cmd_exec (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			PrintText (sess, "Error in fork(2)\n");
 			close(fds[0]);
 			close(fds[1]);
-			free (s);
-		} else
+			g_free (s);
+		}
+		else
 		{
 			/* Parent path */
 			close(fds[1]);
@@ -1940,12 +1926,12 @@ get_bool_cb (int val, getvalinfo *info)
 {
 	char buf[512];
 
-	snprintf (buf, sizeof (buf), "%s %d", info->cmd, val);
+	g_snprintf (buf, sizeof (buf), "%s %d", info->cmd, val);
 	if (is_session (info->sess))
 		handle_command (info->sess, buf, FALSE);
 
-	free (info->cmd);
-	free (info);
+	g_free (info->cmd);
+	g_free (info);
 }
 
 static int
@@ -1956,8 +1942,8 @@ cmd_getbool (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (!word[4][0])
 		return FALSE;
 
-	info = malloc (sizeof (*info));
-	info->cmd = strdup (word[2]);
+	info = g_new (getvalinfo, 1);
+	info->cmd = g_strdup (word[2]);
 	info->sess = sess;
 
 	fe_get_bool (word[3], word_eol[4], get_bool_cb, info);
@@ -1972,13 +1958,13 @@ get_int_cb (int cancel, int val, getvalinfo *info)
 
 	if (!cancel)
 	{
-		snprintf (buf, sizeof (buf), "%s %d", info->cmd, val);
+		g_snprintf (buf, sizeof (buf), "%s %d", info->cmd, val);
 		if (is_session (info->sess))
 			handle_command (info->sess, buf, FALSE);
 	}
 
-	free (info->cmd);
-	free (info);
+	g_free (info->cmd);
+	g_free (info);
 }
 
 static int
@@ -1989,8 +1975,8 @@ cmd_getint (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (!word[4][0])
 		return FALSE;
 
-	info = malloc (sizeof (*info));
-	info->cmd = strdup (word[3]);
+	info = g_new (getvalinfo, 1);
+	info->cmd = g_strdup (word[3]);
 	info->sess = sess;
 
 	fe_get_int (word[4], atoi (word[2]), get_int_cb, info);
@@ -2007,13 +1993,13 @@ get_file_cb (char *cmd, char *file)
       no args */
 	if (file)
 	{
-		snprintf (buf, sizeof (buf), "%s %s", cmd, file);
+		g_snprintf (buf, sizeof (buf), "%s %s", cmd, file);
 		handle_command (current_sess, buf, FALSE);
 	}
 	else
 	{
 		handle_command (current_sess, cmd, FALSE);
-		free (cmd);
+		g_free (cmd);
 	}
 }
 
@@ -2044,7 +2030,7 @@ cmd_getfile (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		idx++;
 	}
 
-	fe_get_file (word[idx+1], word[idx+2], (void *)get_file_cb, strdup (word[idx]), flags);
+	fe_get_file (word[idx+1], word[idx+2], (void *)get_file_cb, g_strdup (word[idx]), flags);
 
 	return TRUE;
 }
@@ -2056,13 +2042,13 @@ get_str_cb (int cancel, char *val, getvalinfo *info)
 
 	if (!cancel)
 	{
-		snprintf (buf, sizeof (buf), "%s %s", info->cmd, val);
+		g_snprintf (buf, sizeof (buf), "%s %s", info->cmd, val);
 		if (is_session (info->sess))
 			handle_command (info->sess, buf, FALSE);
 	}
 
-	free (info->cmd);
-	free (info);
+	g_free (info->cmd);
+	g_free (info);
 }
 
 static int
@@ -2073,8 +2059,8 @@ cmd_getstr (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if (!word[4][0])
 		return FALSE;
 
-	info = malloc (sizeof (*info));
-	info->cmd = strdup (word[3]);
+	info = g_new (getvalinfo, 1);
+	info->cmd = g_strdup (word[3]);
 	info->sess = sess;
 
 	fe_get_str (word[4], word[2], get_str_cb, info);
@@ -2200,7 +2186,7 @@ cmd_help (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	} else
 	{
 		struct popup *pop;
-		char *buf = malloc (4096);
+		char *buf = g_malloc (4096);
 		help_list hl;
 
 		hl.longfmt = longfmt;
@@ -2245,7 +2231,7 @@ cmd_help (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		plugin_command_foreach (sess, &hl, (void *)show_help_line);
 		strcat (buf, "\n");
 		PrintText (sess, buf);
-		free (buf);
+		g_free (buf);
 
 		PrintTextf (sess, "\n%s\n\n", _("Type /HELP <command> for more information, or /HELP -l"));
 	}
@@ -2293,7 +2279,7 @@ cmd_ignore (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			    strchr (mask, '*') == NULL)
 			{
 				mask = tbuf;
-				snprintf (tbuf, TBUFSIZE, "%s!*@*", word[2]);
+				g_snprintf (tbuf, TBUFSIZE, "%s!*@*", word[2]);
 			}
 
 			i = ignore_add (mask, type, TRUE);
@@ -2549,7 +2535,7 @@ cmd_load (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			PrintText (sess, errorstring (errno));
 			g_free (buf);
 		}
-		free (file);
+		g_free (file);
 		return TRUE;
 	}
 
@@ -2562,7 +2548,7 @@ cmd_load (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 
 		file = expand_homedir (word[2]);
 		error = plugin_load (sess, file, arg);
-		free (file);
+		g_free (file);
 
 		if (error)
 			PrintText (sess, error);
@@ -2651,7 +2637,7 @@ cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 		return TRUE;
 	}
 
-	snprintf (tbuf, TBUFSIZE, "\001ACTION %s\001\r", act);
+	g_snprintf (tbuf, TBUFSIZE, "\001ACTION %s\001\r", act);
 	/* first try through DCC CHAT */
 	if (dcc_write_chat (sess->channel, tbuf))
 	{
@@ -2674,7 +2660,7 @@ cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 				if (*split_text)
 					offset += strlen(split_text);
 
-				g_free(split_text);
+				g_free (split_text);
 			}
 
 			sess->server->p_action (sess->server, sess->channel, act + offset);
@@ -2693,17 +2679,26 @@ cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 static int
 cmd_mode (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	/* +channel channels are dying, let those servers whine about modes.
-	 * return info about current channel if available and no info is given */
-	if ((*word[2] == '+') || (*word[2] == 0) || (!is_channel(sess->server, word[2]) &&
-				!(rfc_casecmp(sess->server->nick, word[2]) == 0)))
+	/* We allow omitting the target, so we have to figure it out:
+	 * - Can only use info from channels or dialogs
+	 * - Empty arg is always sess info
+	 * - Assume + is mode not channel
+	 * - We know valid channels and our nick
+	 * - We cannot easily know if other nick or valid mode (Need to store 004)
+	 */
+	if ((sess->type != SESS_CHANNEL && sess->type != SESS_DIALOG)
+	    || (!(*word[2] == '-' || *word[2] == '+' || *word[2] == '\0')
+	        && (is_channel (sess->server, word[2]) || !rfc_casecmp (sess->server->nick, word[2])))
+	   )
+	{
+		sess->server->p_mode (sess->server, word[2], word_eol[3]);
+	}
+	else
 	{
 		if(sess->channel[0] == 0)
 			return FALSE;
 		sess->server->p_mode (sess->server, sess->channel, word_eol[2]);
 	}
-	else
-		sess->server->p_mode (sess->server, word[2], word_eol[3]);
 	return TRUE;
 }
 
@@ -2721,7 +2716,7 @@ mop_cb (struct User *user, multidata *data)
 static int
 cmd_mop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	char **nicks = malloc (sizeof (char *) * (sess->total - sess->ops));
+	char **nicks = g_new0 (char *, sess->total - sess->ops);
 	multidata data;
 
 	data.nicks = nicks;
@@ -2729,7 +2724,7 @@ cmd_mop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	tree_foreach (sess->usertree, (tree_traverse_func *)mop_cb, &data);
 	send_channel_modes (sess, tbuf, nicks, 0, data.i, '+', 'o', 0);
 
-	free (nicks);
+	g_free (nicks);
 
 	return TRUE;
 }
@@ -2780,7 +2775,7 @@ cmd_msg (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 					if (*split_text)
 						offset += strlen(split_text);
 
-					g_free(split_text);
+					g_free (split_text);
 				}
 				sess->server->p_message (sess->server, nick, msg + offset);
 				offset = 0;
@@ -2801,7 +2796,7 @@ cmd_msg (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 					if (*split_text)
 						offset += strlen(split_text);
 
-					g_free(split_text);
+					g_free (split_text);
 				}
 				inbound_chanmsg (newsess->server, NULL, newsess->channel,
 									  newsess->server->nick, msg + offset, TRUE, FALSE,
@@ -2895,7 +2890,7 @@ cmd_notice (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			if (*split_text)
 				offset += strlen(split_text);
 			
-			g_free(split_text);
+			g_free (split_text);
 		}
 
 		sess->server->p_notice (sess->server, word[2], text + offset);
@@ -2991,7 +2986,7 @@ cmd_ping (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 
 	tim = make_ping_time ();
 
-	snprintf (timestring, sizeof (timestring), "%lu", tim);
+	g_snprintf (timestring, sizeof (timestring), "%lu", tim);
 	sess->server->p_ping (sess->server, to, timestring);
 
 	return TRUE;
@@ -3054,7 +3049,7 @@ cmd_query (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 				if (*split_text)
 					offset += strlen(split_text);
 
-				g_free(split_text);
+				g_free (split_text);
 			}
 			sess->server->p_message (sess->server, nick, msg + offset);
 			inbound_chanmsg (nick_sess->server, nick_sess, nick_sess->channel,
@@ -3231,9 +3226,9 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 	if ((addr & 0xffff0000) == 0xc0a80000 ||	/* 192.168.x.x */
 		 (addr & 0xff000000) == 0x0a000000)		/* 10.x.x.x */
 		/* we got a private net address, let's PSEND or it'll fail */
-		snprintf (tbuf, 512, "DCC PSEND %s", word_eol[2]);
+		g_snprintf (tbuf, 512, "DCC PSEND %s", word_eol[2]);
 	else
-		snprintf (tbuf, 512, "DCC SEND %s", word_eol[2]);
+		g_snprintf (tbuf, 512, "DCC SEND %s", word_eol[2]);
 
 	handle_command (sess, tbuf, FALSE);
 
@@ -3418,8 +3413,9 @@ cmd_server (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 			safe_strcpy (serv->password, net->pass, sizeof (serv->password));
 			serv->loginmethod = net->logintype;
 		}
-		else /* Otherwise ensure no password is sent */
+		else /* Otherwise ensure no password is sent or SASL started */
 		{
+			serv->loginmethod = LOGIN_DEFAULT;
 			serv->password[0] = 0;
 		}
 	}
@@ -3484,12 +3480,6 @@ cmd_topic (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 static int
 cmd_tray (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	if (strcmp (word[2], "-b") == 0)
-	{
-		fe_tray_set_balloon (word[3], word[4][0] ? word[4] : NULL);
-		return TRUE;
-	}
-
 	if (strcmp (word[2], "-t") == 0)
 	{
 		fe_tray_set_tooltip (word[3][0] ? word[3] : NULL);
@@ -3533,7 +3523,7 @@ cmd_unignore (struct session *sess, char *tbuf, char *word[],
 		if (strchr (mask, '?') == NULL && strchr (mask, '*') == NULL)
 		{
 			mask = tbuf;
-			snprintf (tbuf, TBUFSIZE, "%s!*@*", word[2]);
+			g_snprintf (tbuf, TBUFSIZE, "%s!*@*", word[2]);
 		}
 		
 		if (ignore_del (mask, NULL))
@@ -3873,7 +3863,7 @@ const struct commands xc_cmds[] = {
 	 N_("ALLCHANL <cmd>, sends a command to all channels on the current server")},
 	{"ALLSERV", cmd_allservers, 0, 0, 1,
 	 N_("ALLSERV <cmd>, sends a command to all servers you're in")},
-	{"AWAY", cmd_away, 1, 0, 1, N_("AWAY [<reason>], sets you away")},
+	{"AWAY", cmd_away, 1, 0, 1, N_("AWAY [<reason>], sets you away (use /BACK to unset)")},
 	{"BACK", cmd_back, 1, 0, 1, N_("BACK, sets you back (not away)")},
 	{"BAN", cmd_ban, 1, 1, 1,
 	 N_("BAN <mask> [<bantype>], bans everyone matching the mask from the current channel. If they are already on the channel this doesn't kick them (needs chanop)")},
@@ -4096,7 +4086,7 @@ usercommand_show_help (session *sess, char *name)
 		pop = (struct popup *) list->data;
 		if (!g_ascii_strcasecmp (pop->name, name))
 		{
-			snprintf (buf, sizeof(buf), _("User Command for: %s\n"), pop->cmd);
+			g_snprintf (buf, sizeof(buf), _("User Command for: %s\n"), pop->cmd);
 			PrintText (sess, buf);
 
 			found = TRUE;
@@ -4123,7 +4113,7 @@ help (session *sess, char *tbuf, char *helpcmd, int quiet)
 	{
 		if (cmd->help)
 		{
-			snprintf (tbuf, TBUFSIZE, _("Usage: %s\n"), _(cmd->help));
+			g_snprintf (tbuf, TBUFSIZE, _("Usage: %s\n"), _(cmd->help));
 			PrintText (sess, tbuf);
 		} else
 		{
@@ -4145,7 +4135,7 @@ help (session *sess, char *tbuf, char *helpcmd, int quiet)
  * - this beast is used for UserCommands, UserlistButtons and CTCP replies   */
 
 int
-auto_insert (char *dest, int destlen, unsigned char *src, char *word[],
+auto_insert (char *dest, gsize destlen, unsigned char *src, char *word[],
 				 char *word_eol[], char *a, char *c, char *d, char *e, char *h,
 				 char *n, char *s, char *u)
 {
@@ -4217,7 +4207,7 @@ auto_insert (char *dest, int destlen, unsigned char *src, char *word[],
 				switch (src[0])
 				{
 				case '%':
-					if ((dest - orig) + 2 >= destlen)
+					if ((dest - orig) + 2u >= destlen)
 						return 2;
 					dest[0] = '%';
 					dest[1] = 0;
@@ -4252,7 +4242,7 @@ auto_insert (char *dest, int destlen, unsigned char *src, char *word[],
 				case 'y':
 					now = time (0);
 					tm_ptr = localtime (&now);
-					snprintf (buf, sizeof (buf), "%4d%02d%02d", 1900 +
+					g_snprintf (buf, sizeof (buf), "%4d%02d%02d", 1900 +
 								 tm_ptr->tm_year, 1 + tm_ptr->tm_mon, tm_ptr->tm_mday);
 					utf = buf;
 					break;
@@ -4311,81 +4301,78 @@ check_special_chars (char *cmd, int do_ascii) /* check for %X */
 	if (!len)
 		return;
 
-	buf = malloc (len + 1);
+	buf = g_malloc (len + 1);
 
-	if (buf)
+	while (cmd[j])
 	{
-		while (cmd[j])
+		switch (cmd[j])
 		{
-			switch (cmd[j])
+		case '%':
+			occur++;
+			if (	do_ascii &&
+					j + 3 < len &&
+					(isdigit ((unsigned char) cmd[j + 1]) && isdigit ((unsigned char) cmd[j + 2]) &&
+					isdigit ((unsigned char) cmd[j + 3])))
 			{
-			case '%':
-				occur++;
-				if (	do_ascii &&
-						j + 3 < len &&
-						(isdigit ((unsigned char) cmd[j + 1]) && isdigit ((unsigned char) cmd[j + 2]) &&
-						isdigit ((unsigned char) cmd[j + 3])))
+				tbuf[0] = cmd[j + 1];
+				tbuf[1] = cmd[j + 2];
+				tbuf[2] = cmd[j + 3];
+				tbuf[3] = 0;
+				buf[i] = atoi (tbuf);
+				utf = g_locale_to_utf8 (buf + i, 1, 0, &utf_len, 0);
+				if (utf)
 				{
-					tbuf[0] = cmd[j + 1];
-					tbuf[1] = cmd[j + 2];
-					tbuf[2] = cmd[j + 3];
-					tbuf[3] = 0;
-					buf[i] = atoi (tbuf);
-					utf = g_locale_to_utf8 (buf + i, 1, 0, &utf_len, 0);
-					if (utf)
-					{
-						memcpy (buf + i, utf, utf_len);
-						g_free (utf);
-						i += (utf_len - 1);
-					}
-					j += 3;
-				} else
+					memcpy (buf + i, utf, utf_len);
+					g_free (utf);
+					i += (utf_len - 1);
+				}
+				j += 3;
+			} else
+			{
+				switch (cmd[j + 1])
 				{
-					switch (cmd[j + 1])
-					{
-					case 'R':
-						buf[i] = '\026';
-						break;
-					case 'U':
-						buf[i] = '\037';
-						break;
-					case 'B':
-						buf[i] = '\002';
-						break;
-					case 'I':
-						buf[i] = '\035';
-						break;
-					case 'C':
-						buf[i] = '\003';
-						break;
-					case 'O':
-						buf[i] = '\017';
-						break;
-					case 'H':	/* CL: invisible text code */
-						buf[i] = HIDDEN_CHAR;
-						break;
-					case '%':
-						buf[i] = '%';
-						break;
-					default:
-						buf[i] = '%';
-						j--;
-						break;
-					}
-					j++;
+				case 'R':
+					buf[i] = '\026';
+					break;
+				case 'U':
+					buf[i] = '\037';
+					break;
+				case 'B':
+					buf[i] = '\002';
+					break;
+				case 'I':
+					buf[i] = '\035';
+					break;
+				case 'C':
+					buf[i] = '\003';
+					break;
+				case 'O':
+					buf[i] = '\017';
+					break;
+				case 'H':	/* CL: invisible text code */
+					buf[i] = HIDDEN_CHAR;
+					break;
+				case '%':
+					buf[i] = '%';
+					break;
+				default:
+					buf[i] = '%';
+					j--;
 					break;
-			default:
-					buf[i] = cmd[j];
 				}
+				j++;
+				break;
+		default:
+				buf[i] = cmd[j];
 			}
-			j++;
-			i++;
 		}
-		buf[i] = 0;
-		if (occur)
-			strcpy (cmd, buf);
-		free (buf);
+		j++;
+		i++;
 	}
+	buf[i] = 0;
+	if (occur)
+		strcpy (cmd, buf);
+	g_free (buf);
 }
 
 typedef struct
@@ -4408,7 +4395,7 @@ nick_comp_cb (struct User *user, nickdata *data)
 		lenu = strlen (user->nick);
 		if (lenu == data->len)
 		{
-			snprintf (data->tbuf, TBUFSIZE, "%s%s", user->nick, data->space);
+			g_snprintf (data->tbuf, TBUFSIZE, "%s%s", user->nick, data->space);
 			data->len = -1;
 			return FALSE;
 		} else if (lenu < data->bestlen)
@@ -4452,7 +4439,7 @@ perform_nick_completion (struct session *sess, char *cmd, char *tbuf)
 
 				if (data.best)
 				{
-					snprintf (tbuf, TBUFSIZE, "%s%s", data.best->nick, space - 1);
+					g_snprintf (tbuf, TBUFSIZE, "%s%s", data.best->nick, space - 1);
 					return;
 				}
 			}
@@ -4485,12 +4472,10 @@ handle_say (session *sess, char *text, int check_spch)
 	struct DCC *dcc;
 	char *word[PDIWORDS+1];
 	char *word_eol[PDIWORDS+1];
-	char pdibuf_static[1024];
-	char newcmd_static[1024];
-	char *pdibuf = pdibuf_static;
-	char *newcmd = newcmd_static;
+	char *pdibuf;
+	char *newcmd;
 	int len;
-	int newcmdlen = sizeof newcmd_static;
+	int newcmdlen;
 	message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT;
 
 	if (strcmp (sess->channel, "(lastlog)") == 0)
@@ -4500,11 +4485,9 @@ handle_say (session *sess, char *text, int check_spch)
 	}
 
 	len = strlen (text);
-	if (len >= sizeof pdibuf_static)
-		pdibuf = malloc (len + 1);
-
-	if (len + NICKLEN >= newcmdlen)
-		newcmd = malloc (newcmdlen = len + NICKLEN + 1);
+	pdibuf = g_malloc (len + 1);
+	newcmdlen = MAX(len + NICKLEN + 1, TBUFSIZE);
+	newcmd = g_malloc (newcmdlen);
 
 	if (check_spch && prefs.hex_input_perc_color)
 		check_special_chars (text, prefs.hex_input_perc_ascii);
@@ -4565,7 +4548,7 @@ handle_say (session *sess, char *text, int check_spch)
 			if (*split_text)
 				offset += strlen(split_text);
 			
-			g_free(split_text);
+			g_free (split_text);
 		}
 
 		inbound_chanmsg (sess->server, sess, sess->channel, sess->server->nick,
@@ -4577,11 +4560,9 @@ handle_say (session *sess, char *text, int check_spch)
 	}
 
 xit:
-	if (pdibuf != pdibuf_static)
-		free (pdibuf);
+	g_free (pdibuf);
 
-	if (newcmd != newcmd_static)
-		free (newcmd);
+	g_free (newcmd);
 }
 
 char *
@@ -4675,8 +4656,6 @@ handle_command (session *sess, char *cmd, int check_spch)
 	char *word_eol[PDIWORDS+1];
 	static int command_level = 0;
 	struct commands *int_cmd;
-	char pdibuf_static[1024];
-	char tbuf_static[TBUFSIZE];
 	char *pdibuf;
 	char *tbuf;
 	int len;
@@ -4691,23 +4670,8 @@ handle_command (session *sess, char *cmd, int check_spch)
 	/* anything below MUST DEC command_level before returning */
 
 	len = strlen (cmd);
-	if (len >= sizeof (pdibuf_static))
-	{
-		pdibuf = malloc (len + 1);
-	}
-	else
-	{
-		pdibuf = pdibuf_static;
-	}
-
-	if ((len * 2) >= sizeof (tbuf_static))
-	{
-		tbuf = malloc ((len * 2) + 1);
-	}
-	else
-	{
-		tbuf = tbuf_static;
-	}
+	pdibuf = g_malloc (len + 1);
+	tbuf = g_malloc (MAX(TBUFSIZE, (len * 2) + 1));
 
 	/* split the text into words and word_eol */
 	process_data_init (pdibuf, cmd, word, word_eol, TRUE, TRUE);
@@ -4786,13 +4750,13 @@ handle_command (session *sess, char *cmd, int check_spch)
 	}
 	else
 	{
-		/* unknown command, just send it to the server and hope */
 		if (!sess->server->connected)
 		{
-			PrintText (sess, _("Unknown Command. Try /help\n"));
+			PrintTextf (sess, _("Unknown Command %s. Try /help\n"), word[1]);
 		}
 		else
 		{
+			/* unknown command, just send it to the server and hope */
 			sess->server->p_raw (sess->server, cmd);
 		}
 	}
@@ -4800,15 +4764,8 @@ handle_command (session *sess, char *cmd, int check_spch)
 xit:
 	command_level--;
 
-	if (pdibuf != pdibuf_static)
-	{
-		free (pdibuf);
-	}
-
-	if (tbuf != tbuf_static)
-	{
-		free (tbuf);
-	}
+	g_free (pdibuf);
+	g_free (tbuf);
 
 	return ret;
 }
diff --git a/src/common/outbound.h b/src/common/outbound.h
index b9fe6331..490a58ca 100644
--- a/src/common/outbound.h
+++ b/src/common/outbound.h
@@ -25,7 +25,7 @@
 extern const struct commands xc_cmds[];
 extern GSList *menu_list;
 
-int auto_insert (char *dest, int destlen, unsigned char *src, char *word[], char *word_eol[],
+int auto_insert (char *dest, gsize destlen, unsigned char *src, char *word[], char *word_eol[],
 				 char *a, char *c, char *d, char *e, char *h, char *n, char *s, char *u);
 char *command_insert_vars (session *sess, char *cmd);
 int handle_command (session *sess, char *cmd, int check_spch);
diff --git a/src/common/plugin-identd.c b/src/common/plugin-identd.c
new file mode 100644
index 00000000..ce1bd1e6
--- /dev/null
+++ b/src/common/plugin-identd.c
@@ -0,0 +1,220 @@
+/* HexChat
+*
+* 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
+*/
+
+#include "config.h"
+
+#include <string.h>
+#include <gio/gio.h>
+#include "hexchat-plugin.h"
+
+#define _(x) hexchat_gettext(ph,x)
+
+static hexchat_plugin *ph;
+static GSocketService *service;
+static GHashTable *responses;
+
+typedef struct ident_info
+{
+	GSocketConnection *conn;
+	gchar *username;
+	gchar read_buf[16];
+} ident_info;
+
+static int
+identd_cleanup_response_cb (gpointer userdata)
+{
+	g_return_val_if_fail (responses != NULL, 0);
+
+	g_hash_table_remove (responses, userdata);
+
+	return 0;
+}
+
+static int
+identd_command_cb (char *word[], char *word_eol[], void *userdata)
+{
+	g_return_val_if_fail (responses != NULL, HEXCHAT_EAT_ALL);
+
+	if (service == NULL) /* If we are not running plugins can handle it */
+		return HEXCHAT_EAT_HEXCHAT;
+
+	if (word[2] && *word[2] && word[3] && *word[3])
+	{
+		guint64 port = g_ascii_strtoull (word[2], NULL, 0);
+
+		if (port && port <= G_MAXUINT16)
+		{
+			g_hash_table_insert (responses, GINT_TO_POINTER (port), g_strdup (word[3]));
+			/* Automatically remove entry after 30 seconds */
+			hexchat_hook_timer (ph, 30000, identd_cleanup_response_cb, GINT_TO_POINTER (port));
+		}
+	}
+	else
+	{
+		hexchat_command (ph, "HELP IDENTD");
+	}
+
+	return HEXCHAT_EAT_ALL;
+}
+
+static void
+identd_write_ready (GOutputStream *stream, GAsyncResult *res, ident_info *info)
+{
+	g_output_stream_write_finish (stream, res, NULL);
+
+	g_free (info->username);
+	g_object_unref (info->conn);
+	g_free (info);
+}
+
+static void
+identd_read_ready (GInputStream *in_stream, GAsyncResult *res, ident_info *info)
+{
+	GSocketAddress *sok_addr;
+	GOutputStream *out_stream;
+	guint64 local, remote;
+	gchar buf[512], *p;
+
+	if (g_input_stream_read_finish (in_stream, res, NULL))
+	{
+		local = g_ascii_strtoull (info->read_buf, NULL, 0);
+		p = strchr (info->read_buf, ',');
+		if (!p)
+			goto cleanup;
+
+		remote = g_ascii_strtoull (p + 1, NULL, 0);
+
+		if (!local || !remote || local > G_MAXUINT16 || remote > G_MAXUINT16)
+			goto cleanup;
+
+		info->username = g_strdup (g_hash_table_lookup (responses, GINT_TO_POINTER (local)));
+		if (!info->username)
+			goto cleanup;
+		g_hash_table_remove (responses, GINT_TO_POINTER (local));
+
+		if ((sok_addr = g_socket_connection_get_remote_address (info->conn, NULL)))
+		{
+			GInetAddress *inet_addr;
+			gchar *addr;
+
+			inet_addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (sok_addr));
+			addr = g_inet_address_to_string (inet_addr);
+
+			hexchat_printf (ph, _("*\tServicing ident request from %s as %s"), addr, info->username);
+
+			g_object_unref (sok_addr);
+			g_object_unref (inet_addr);
+			g_free (addr);
+		}
+
+		g_snprintf (buf, sizeof (buf), "%"G_GUINT16_FORMAT", %"G_GUINT16_FORMAT" : USERID : UNIX : %s\r\n", (guint16)local, (guint16)remote, info->username);
+		out_stream = g_io_stream_get_output_stream (G_IO_STREAM (info->conn));
+		g_output_stream_write_async (out_stream, buf, strlen (buf), G_PRIORITY_DEFAULT,
+									NULL, (GAsyncReadyCallback)identd_write_ready, info);
+	}
+
+	return;
+
+cleanup:
+	g_object_unref (info->conn);
+	g_free (info);
+}
+
+static gboolean
+identd_incoming_cb (GSocketService *service, GSocketConnection *conn,
+					GObject *source, gpointer userdata)
+{
+	GInputStream *stream;
+	ident_info *info;
+
+	info = g_new0 (ident_info, 1);
+
+	info->conn = conn;
+	g_object_ref (conn);
+
+	stream = g_io_stream_get_input_stream (G_IO_STREAM (conn));
+	g_input_stream_read_async (stream, info->read_buf, sizeof (info->read_buf), G_PRIORITY_DEFAULT,
+							NULL, (GAsyncReadyCallback)identd_read_ready, info);
+
+	return TRUE;
+}
+
+static void
+identd_start_server (void)
+{
+	GError *error = NULL;
+	int enabled, port = 113;
+
+	if (hexchat_get_prefs (ph, "identd", NULL, &enabled) == 3)
+	{
+		if (!enabled)
+			return;
+	}
+	if (hexchat_get_prefs (ph, "identd_port", NULL, &port) == 2 && (port <= 0 || port > G_MAXUINT16))
+	{
+		port = 113;
+	}
+
+	service = g_socket_service_new ();
+
+	g_socket_listener_add_inet_port (G_SOCKET_LISTENER (service), port, NULL, &error);
+	if (error)
+	{
+		hexchat_printf (ph, _("*\tError starting identd server: %s"), error->message);
+
+		g_object_unref (service);
+		service = NULL;
+		return;
+	}
+	/*hexchat_printf (ph, "*\tIdentd listening on port: %d", port); */
+
+	g_signal_connect (G_OBJECT (service), "incoming", G_CALLBACK(identd_incoming_cb), NULL);
+	g_socket_service_start (service);
+}
+
+int
+identd_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name,
+					char **plugin_desc, char **plugin_version, char *arg)
+{
+	ph = plugin_handle;
+	*plugin_name = "";
+	*plugin_desc = "";
+	*plugin_version = "";
+
+
+	responses = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+	hexchat_hook_command (ph, "IDENTD", HEXCHAT_PRI_NORM, identd_command_cb,
+						_("IDENTD <port> <username>"), NULL);
+
+	identd_start_server ();
+
+	return 1; /* This must always succeed for /identd to work */
+}
+
+int
+identd_plugin_deinit (void)
+{
+	if (service)
+	{
+		g_socket_service_stop (service);
+		g_object_unref (service);
+	}
+
+	g_hash_table_destroy (responses);
+
+	return 1;
+}
diff --git a/src/common/identd.h b/src/common/plugin-identd.h
index 3b29135f..5efc2600 100644
--- a/src/common/identd.h
+++ b/src/common/plugin-identd.h
@@ -17,9 +17,12 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#ifndef HEXCHAT_IDENTD_H
-#define HEXCHAT_IDENTD_H
+#ifndef HEXCHAT_PLUGIN_IDENTD_H
+#define HEXCHAT_PLUGIN_IDENTD_H
 
-void identd_start (char *username);
+int identd_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name,
+				char **plugin_desc, char **plugin_version, char *arg);
+
+int identd_plugin_deinit ();
 
 #endif
diff --git a/src/common/plugin-timer.c b/src/common/plugin-timer.c
index e6944330..d0c82c28 100644
--- a/src/common/plugin-timer.c
+++ b/src/common/plugin-timer.c
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <glib.h>
@@ -43,7 +45,7 @@ typedef struct
 	char *command;
 	int ref;
 	int repeat;
-	float timeout;
+	int timeout;
 	unsigned int forever:1;
 } timer;
 
@@ -51,9 +53,9 @@ static void
 timer_del (timer *tim)
 {
 	timer_list = g_slist_remove (timer_list, tim);
-	free (tim->command);
+	g_free (tim->command);
 	hexchat_unhook (ph, tim->hook);
-	free (tim);
+	g_free (tim);
 }
 
 static void
@@ -99,7 +101,7 @@ timeout_cb (timer *tim)
 }
 
 static void
-timer_add (int ref, float timeout, int repeat, char *command)
+timer_add (int ref, int timeout, int repeat, char *command)
 {
 	timer *tim;
 	GSList *list;
@@ -117,18 +119,18 @@ timer_add (int ref, float timeout, int repeat, char *command)
 		}
 	}
 
-	tim = malloc (sizeof (timer));
+	tim = g_new (timer, 1);
 	tim->ref = ref;
 	tim->repeat = repeat;
 	tim->timeout = timeout;
-	tim->command = strdup (command);
+	tim->command = g_strdup (command);
 	tim->context = hexchat_get_context (ph);
 	tim->forever = FALSE;
 
 	if (repeat == 0)
 		tim->forever = TRUE;
 
-	tim->hook = hexchat_hook_timer (ph, timeout * 1000.0, (void *)timeout_cb, tim);
+	tim->hook = hexchat_hook_timer (ph, timeout, (void *)timeout_cb, tim);
 	timer_list = g_slist_append (timer_list, tim);
 }
 
@@ -150,7 +152,7 @@ timer_showlist (void)
 	while (list)
 	{
 		tim = list->data;
-		hexchat_printf (ph, _("%5d %8.1f %7d  %s\n"), tim->ref, tim->timeout,
+		hexchat_printf (ph, _("%5d %8.1f %7d  %s\n"), tim->ref, tim->timeout / 1000.0f,
 						  tim->repeat, tim->command);
 		list = list->next;
 	}
@@ -160,7 +162,7 @@ static int
 timer_cb (char *word[], char *word_eol[], void *userdata)
 {
 	int repeat = 1;
-	float timeout;
+	double timeout;
 	int offset = 0;
 	int ref = 0;
 	int quiet = FALSE;
@@ -199,10 +201,10 @@ timer_cb (char *word[], char *word_eol[], void *userdata)
 	timeout = atof (word[2 + offset]);
 	command = word_eol[3 + offset];
 
-	if (timeout < 0.1 || !command[0])
+	if (timeout < 0.1 || timeout * 1000 > INT_MAX || !command[0])
 		hexchat_print (ph, HELP);
 	else
-		timer_add (ref, timeout, repeat, command);
+		timer_add (ref, (int) timeout * 1000, repeat, command);
 
 	return HEXCHAT_EAT_HEXCHAT;
 }
diff --git a/src/common/plugin.c b/src/common/plugin.c
index d83b69ff..a397c878 100644
--- a/src/common/plugin.c
+++ b/src/common/plugin.c
@@ -161,16 +161,12 @@ plugin_free (hexchat_plugin *pl, int do_deinit, int allow_refuse)
 xit:
 	if (pl->free_strings)
 	{
-		if (pl->name)
-			free (pl->name);
-		if (pl->desc)
-			free (pl->desc);
-		if (pl->version)
-			free (pl->version);
+		g_free (pl->name);
+		g_free (pl->desc);
+		g_free (pl->version);
 	}
-	if (pl->filename)
-		free ((char *)pl->filename);
-	free (pl);
+	g_free ((char *)pl->filename);
+	g_free (pl);
 
 	plugin_list = g_slist_remove (plugin_list, pl);
 
@@ -188,7 +184,7 @@ plugin_list_add (hexchat_context *ctx, char *filename, const char *name,
 {
 	hexchat_plugin *pl;
 
-	pl = malloc (sizeof (hexchat_plugin));
+	pl = g_new (hexchat_plugin, 1);
 	pl->handle = handle;
 	pl->filename = filename;
 	pl->context = ctx;
@@ -239,9 +235,7 @@ plugin_add (session *sess, char *filename, void *handle, void *init_func,
 	hexchat_plugin *pl;
 	char *file;
 
-	file = NULL;
-	if (filename)
-		file = strdup (filename);
+	file = g_strdup (filename);
 
 	pl = plugin_list_add (sess, file, file, NULL, NULL, handle, deinit_func,
 								 fake, FALSE);
@@ -361,15 +355,11 @@ plugin_kill_all (void)
 
 #ifdef USE_PLUGIN
 
-/* load a plugin from a filename. Returns: NULL-success or an error string */
-
-char *
-plugin_load (session *sess, char *filename, char *arg)
+GModule *
+module_load (char *filename)
 {
 	void *handle;
 	char *filepart;
-	hexchat_init_func *init_func;
-	hexchat_deinit_func *deinit_func;
 	char *pluginpath;
 
 	/* get the filename without path */
@@ -389,6 +379,18 @@ plugin_load (session *sess, char *filename, char *arg)
 		handle = g_module_open (filename, 0);
 	}
 
+	return handle;
+}
+
+/* load a plugin from a filename. Returns: NULL-success or an error string */
+
+char *
+plugin_load (session *sess, char *filename, char *arg)
+{
+	GModule *handle = module_load (filename);
+	hexchat_init_func *init_func;
+	hexchat_deinit_func *deinit_func;
+
 	if (handle == NULL)
 		return (char *)g_module_error ();
 
@@ -596,7 +598,7 @@ xit:
 		if (!hook || hook->type == HOOK_DELETED)
 		{
 			hook_list = g_slist_remove (hook_list, hook);
-			free (hook);
+			g_free (hook);
 		}
 		list = next;
 	}
@@ -615,13 +617,7 @@ plugin_emit_command (session *sess, char *name, char *word[], char *word_eol[])
 hexchat_event_attrs *
 hexchat_event_attrs_create (hexchat_plugin *ph)
 {
-	hexchat_event_attrs *attrs;
-
-	attrs = g_malloc (sizeof (*attrs));
-
-	attrs->server_time_utc = (time_t) 0;
-
-	return attrs;
+	return g_new0 (hexchat_event_attrs, 1);
 }
 
 void
@@ -671,26 +667,31 @@ plugin_emit_dummy_print (session *sess, char *name)
 }
 
 int
-plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval,
-							 int len, char *string)
+plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, gunichar key)
 {
 	char *word[PDIWORDS];
 	char keyval_str[16];
 	char state_str[16];
 	char len_str[16];
-	int i;
+	char key_str[7];
+	int i, len;
 
 	if (!hook_list)
 		return 0;
 
 	sprintf (keyval_str, "%u", keyval);
 	sprintf (state_str, "%u", state);
+	if (!key)
+		len = 0;
+	else
+		len = g_unichar_to_utf8 (key, key_str);
+	key_str[len] = '\0';
 	sprintf (len_str, "%d", len);
 
 	word[0] = "Key Press";
 	word[1] = keyval_str;
 	word[2] = state_str;
-	word[3] = string;
+	word[3] = key_str;
 	word[4] = len_str;
 	for (i = 5; i < PDIWORDS; i++)
 		word[i] = "\000";
@@ -796,15 +797,11 @@ plugin_add_hook (hexchat_plugin *pl, int type, int pri, const char *name,
 {
 	hexchat_hook *hook;
 
-	hook = malloc (sizeof (hexchat_hook));
-	memset (hook, 0, sizeof (hexchat_hook));
-
+	hook = g_new0 (hexchat_hook, 1);
 	hook->type = type;
 	hook->pri = pri;
-	if (name)
-		hook->name = strdup (name);
-	if (help_text)
-		hook->help_text = strdup (help_text);
+	hook->name = g_strdup (name);
+	hook->help_text = g_strdup (help_text);
 	hook->callback = callb;
 	hook->pl = pl;
 	hook->userdata = userdata;
@@ -892,10 +889,8 @@ hexchat_unhook (hexchat_plugin *ph, hexchat_hook *hook)
 
 	hook->type = HOOK_DELETED;	/* expunge later */
 
-	if (hook->name)
-		free (hook->name);	/* NULL for timers & fds */
-	if (hook->help_text)
-		free (hook->help_text);	/* NULL for non-commands */
+	g_free (hook->name);	/* NULL for timers & fds */
+	g_free (hook->help_text);	/* NULL for non-commands */
 
 	return hook->userdata;
 }
@@ -988,8 +983,7 @@ hexchat_printf (hexchat_plugin *ph, const char *format, ...)
 void
 hexchat_command (hexchat_plugin *ph, const char *command)
 {
-	char *conv;
-	int len = -1;
+	char *command_utf8;
 
 	if (!is_session (ph->context))
 	{
@@ -998,9 +992,9 @@ hexchat_command (hexchat_plugin *ph, const char *command)
 	}
 
 	/* scripts/plugins continue to send non-UTF8... *sigh* */
-	conv = text_validate ((char **)&command, &len);
-	handle_command (ph->context, (char *)command, FALSE);
-	g_free (conv);
+	command_utf8 = text_fixup_invalid_utf8 (command, -1, NULL);
+	handle_command (ph->context, command_utf8, FALSE);
+	g_free (command_utf8);
 }
 
 void
@@ -1263,8 +1257,7 @@ hexchat_list_get (hexchat_plugin *ph, const char *name)
 {
 	hexchat_list *list;
 
-	list = malloc (sizeof (hexchat_list));
-	list->pos = NULL;
+	list = g_new0 (hexchat_list, 1);
 
 	switch (str_hash (name))
 	{
@@ -1299,7 +1292,7 @@ hexchat_list_get (hexchat_plugin *ph, const char *name)
 		}	/* fall through */
 
 	default:
-		free (list);
+		g_free (list);
 		return NULL;
 	}
 
@@ -1311,7 +1304,7 @@ hexchat_list_free (hexchat_plugin *ph, hexchat_list *xlist)
 {
 	if (xlist->type == LIST_USERS)
 		g_slist_free (xlist->head);
-	free (xlist);
+	g_free (xlist);
 }
 
 int
@@ -1531,7 +1524,14 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name)
 		case 0x34207553: /* address32 */
 			return ((struct DCC *)data)->addr;
 		case 0x181a6: /* cps */
-			return ((struct DCC *)data)->cps;
+		{
+			gint64 cps = ((struct DCC *)data)->cps;
+			if (cps <= INT_MAX)
+			{
+				return (int) cps;
+			}
+			return INT_MAX;
+		}
 		case 0x349881: /* port */
 			return ((struct DCC *)data)->port;
 		case 0x1b254: /* pos */
@@ -1569,7 +1569,7 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name)
 		case 0x5cfee87:	/* flags */
 			/* used if text_strip is unset */                    /* 16 */
 			tmp <<= 1;
-			tmp = ((struct session *)data)->text_strip;          /* 15 */
+			tmp |= ((struct session *)data)->text_strip;          /* 15 */
 			tmp <<= 1;
 			/* used if text_scrollback is unset */               /* 14 */
 			tmp <<= 1;
@@ -1644,8 +1644,8 @@ hexchat_plugingui_add (hexchat_plugin *ph, const char *filename,
 							const char *version, char *reserved)
 {
 #ifdef USE_PLUGIN
-	ph = plugin_list_add (NULL, strdup (filename), strdup (name), strdup (desc),
-								 strdup (version), NULL, NULL, TRUE, TRUE);
+	ph = plugin_list_add (NULL, g_strdup (filename), g_strdup (name), g_strdup (desc),
+								 g_strdup (version), NULL, NULL, TRUE, TRUE);
 	fe_pluginlist_update ();
 #endif
 
@@ -1771,6 +1771,8 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
 	{
 		g_free (confname);
 		g_free (confname_tmp);
+		if (fpIn)
+			fclose (fpIn);
 		return 0;
 	}
 	else if (fpIn == NULL)	/* no previous config file, no parsing */
@@ -1819,7 +1821,7 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char
 	{
 		prevSetting = 0;
 
-		while (fscanf (fpIn, " %[^\n]", line_bufp) != EOF)	/* read whole lines including whitespaces */
+		while (fscanf (fpIn, " %511[^\n]", line_bufp) != EOF)	/* read whole lines including whitespaces */
 		{
 			buffer_tmp = g_strdup_printf ("%s ", var);	/* add one space, this way it works against var - var2 checks too */
 
@@ -1908,7 +1910,6 @@ hexchat_pluginpref_get_str_real (hexchat_plugin *pl, const char *var, char *dest
 		g_free (confname);
 		return 0;
 	}
-
 	g_free (confname);
 
 	if (!cfg_get_str (cfg, var, buf, sizeof(buf)))
@@ -1937,7 +1938,7 @@ hexchat_pluginpref_set_int (hexchat_plugin *pl, const char *var, int value)
 {
 	char buffer[12];
 
-	snprintf (buffer, sizeof (buffer), "%d", value);
+	g_snprintf (buffer, sizeof (buffer), "%d", value);
 	return hexchat_pluginpref_set_str_real (pl, var, buffer, 1);
 }
 
diff --git a/src/common/plugin.h b/src/common/plugin.h
index cd3f70a8..5743f39a 100644
--- a/src/common/plugin.h
+++ b/src/common/plugin.h
@@ -163,6 +163,7 @@ struct _hexchat_plugin
 };
 #endif
 
+GModule *module_load (char *filename);
 char *plugin_load (session *sess, char *filename, char *arg);
 int plugin_reload (session *sess, char *name, int by_filename);
 void plugin_add (session *sess, char *filename, void *handle, void *init_func, void *deinit_func, char *arg, int fake);
@@ -174,7 +175,7 @@ int plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[
 						time_t server_time);
 int plugin_emit_print (session *sess, char *word[], time_t server_time);
 int plugin_emit_dummy_print (session *sess, char *name);
-int plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, int len, char *string);
+int plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, gunichar key);
 GList* plugin_command_list(GList *tmp_list);
 int plugin_show_help (session *sess, char *cmd);
 void plugin_command_foreach (session *sess, void *userdata, void (*cb) (session *sess, void *userdata, char *name, char *usage));
diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c
index 34b4ece1..d8f15cb5 100644
--- a/src/common/proto-irc.c
+++ b/src/common/proto-irc.c
@@ -429,7 +429,7 @@ irc_raw (server *serv, char *raw)
 		len = strlen (raw);
 		if (len < sizeof (tbuf) - 3)
 		{
-			len = snprintf (tbuf, sizeof (tbuf), "%s\r\n", raw);
+			len = g_snprintf (tbuf, sizeof (tbuf), "%s\r\n", raw);
 			tcp_send_len (serv, tbuf, len);
 		} else
 		{
@@ -590,7 +590,7 @@ process_numeric (session * sess, int n,
 			char *tim;
 			char outbuf[64];
 
-			snprintf (outbuf, sizeof (outbuf),
+			g_snprintf (outbuf, sizeof (outbuf),
 						"%02ld:%02ld:%02ld", idle / 3600, (idle / 60) % 60,
 						idle % 60);
 			if (timestamp == 0)
@@ -666,7 +666,6 @@ process_numeric (session * sess, int n,
 			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMODES, sess, word[4], word_eol[5],
 										  NULL, NULL, 0, tags_data->timestamp);
 		fe_update_mode_buttons (sess, 'c', '-');
-		fe_update_mode_buttons (sess, 'r', '-');
 		fe_update_mode_buttons (sess, 't', '-');
 		fe_update_mode_buttons (sess, 'n', '-');
 		fe_update_mode_buttons (sess, 'i', '-');
@@ -816,10 +815,7 @@ process_numeric (session * sess, int n,
 	case 349:	/* end of exemption list */
 		sess = find_channel (serv, word[4]);
 		if (!sess)
-		{
-			sess = serv->front_session;
 			goto def;
-		}
 		if (!fe_ban_list_end (sess, 349))
 			goto def;
 		break;
@@ -844,10 +840,7 @@ process_numeric (session * sess, int n,
 	case 368:
 		sess = find_channel (serv, word[4]);
 		if (!sess)
-		{
-			sess = serv->front_session;
 			goto def;
-		}
 		if (!fe_ban_list_end (sess, 368))
 			goto def;
 		break;
@@ -1355,8 +1348,8 @@ process_named_servermsg (session *sess, char *buf, char *rawname, char *word_eol
 /* Returns the timezone offset. This should be the same as the variable
  * "timezone" in time.h, but *BSD doesn't have it.
  */
-static int
-get_timezone(void)
+static time_t
+get_timezone (void)
 {
 	struct tm tm_utc, tm_local;
 	time_t t, time_utc, time_local;
@@ -1481,13 +1474,10 @@ irc_inline (server *serv, char *buf, int len)
 	char *type, *text;
 	char *word[PDIWORDS+1];
 	char *word_eol[PDIWORDS+1];
-	char pdibuf_static[522]; /* 1 line can potentially be 512*6 in utf8 */
-	char *pdibuf = pdibuf_static;
+	char *pdibuf;
 	message_tags_data tags_data = MESSAGE_TAGS_DATA_INIT;
 
-	/* need more than 522? fall back to malloc */
-	if (len >= sizeof (pdibuf_static))
-		pdibuf = malloc (len + 1);
+	pdibuf = g_malloc (len + 1);
 
 	sess = serv->front_session;
 
@@ -1509,7 +1499,7 @@ irc_inline (server *serv, char *buf, int len)
 		handle_message_tags(serv, tags, &tags_data);
 	}
 
-	url_check_line (buf, len);
+	url_check_line (buf);
 
 	/* split line into words and words_to_end_of_line */
 	process_data_init (pdibuf, buf, word, word_eol, FALSE, FALSE);
@@ -1566,8 +1556,7 @@ irc_inline (server *serv, char *buf, int len)
 	}
 
 xit:
-	if (pdibuf != pdibuf_static)
-		free (pdibuf);
+	g_free (pdibuf);
 }
 
 void
diff --git a/src/common/server.c b/src/common/server.c
index 98785937..8ff81553 100644
--- a/src/common/server.c
+++ b/src/common/server.c
@@ -21,8 +21,6 @@
  *      Inferno Nettverk A/S, Norway.  All rights reserved.
  */
 
-/*#define DEBUG_MSPROXY*/
-
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -63,20 +61,11 @@
 #include "ssl.h"
 #endif
 
-#ifdef USE_MSPROXY
-#include "msproxy.h"
-#endif
-
-#ifdef WIN32
-#include "identd.h"
-#endif
-
 #ifdef USE_LIBPROXY
 #include <proxy.h>
 #endif
 
 #ifdef USE_OPENSSL
-extern SSL_CTX *ctx;				  /* hexchat.c */
 /* local variables */
 static struct session *g_sess = NULL;
 #endif
@@ -97,57 +86,21 @@ extern pxProxyFactory *libproxy_factory;
    send via SSL. server/dcc both use this function. */
 
 int
-tcp_send_real (void *ssl, int sok, char *encoding, int using_irc, char *buf, int len)
+tcp_send_real (void *ssl, int sok, GIConv write_converter, char *buf, int len)
 {
 	int ret;
-	char *locale;
-	gsize loc_len;
-
-	if (encoding == NULL)	/* system */
-	{
-		locale = NULL;
-		if (!prefs.utf8_locale)
-		{
-			const gchar *charset;
-
-			g_get_charset (&charset);
-			locale = g_convert_with_fallback (buf, len, charset, "UTF-8",
-														 "?", 0, &loc_len, 0);
-		}
-	} else
-	{
-		if (using_irc)	/* using "IRC" encoding (CP1252/UTF-8 hybrid) */
-			/* if all chars fit inside CP1252, use that. Otherwise this
-			   returns NULL and we send UTF-8. */
-			locale = g_convert (buf, len, "CP1252", "UTF-8", 0, &loc_len, 0);
-		else
-			locale = g_convert_with_fallback (buf, len, encoding, "UTF-8",
-														 "?", 0, &loc_len, 0);
-	}
 
-	if (locale)
-	{
-		len = loc_len;
+	gsize buf_encoded_len;
+	gchar *buf_encoded = text_convert_invalid (buf, len, write_converter, "?", &buf_encoded_len);
 #ifdef USE_OPENSSL
-		if (!ssl)
-			ret = send (sok, locale, len, 0);
-		else
-			ret = _SSL_send (ssl, locale, len);
-#else
-		ret = send (sok, locale, len, 0);
-#endif
-		g_free (locale);
-	} else
-	{
-#ifdef USE_OPENSSL
-		if (!ssl)
-			ret = send (sok, buf, len, 0);
-		else
-			ret = _SSL_send (ssl, buf, len);
+	if (!ssl)
+		ret = send (sok, buf_encoded, buf_encoded_len, 0);
+	else
+		ret = _SSL_send (ssl, buf_encoded, buf_encoded_len);
 #else
-		ret = send (sok, buf, len, 0);
+	ret = send (sok, buf_encoded, buf_encoded_len, 0);
 #endif
-	}
+	g_free (buf_encoded);
 
 	return ret;
 }
@@ -157,10 +110,9 @@ server_send_real (server *serv, char *buf, int len)
 {
 	fe_add_rawlog (serv, buf, len, TRUE);
 
-	url_check_line (buf, len);
+	url_check_line (buf);
 
-	return tcp_send_real (serv->ssl, serv->sok, serv->encoding, serv->using_irc,
-								 buf, len);
+	return tcp_send_real (serv->ssl, serv->sok, serv->write_converter, buf, len);
 }
 
 /* new throttling system, uses the same method as the Undernet
@@ -213,7 +165,7 @@ tcp_send_queue (server *serv)
 
 				buf--;
 				serv->outbound_queue = g_slist_remove (serv->outbound_queue, buf);
-				free (buf);
+				g_free (buf);
 				list = serv->outbound_queue;
 			} else
 			{
@@ -235,7 +187,7 @@ tcp_send_len (server *serv, char *buf, int len)
 	if (!prefs.hex_net_throttle)
 		return server_send_real (serv, buf, len);
 
-	dbuf = malloc (len + 2);	/* first byte is the priority */
+	dbuf = g_malloc (len + 2);	/* first byte is the priority */
 	dbuf[0] = 2;	/* pri 2 for most things */
 	memcpy (dbuf + 1, buf, len);
 	dbuf[len + 1] = 0;
@@ -266,12 +218,6 @@ tcp_send_len (server *serv, char *buf, int len)
 	return 1;
 }
 
-/*int
-tcp_send (server *serv, char *buf)
-{
-	return tcp_send_len (serv, buf, strlen (buf));
-}*/
-
 void
 tcp_sendf (server *serv, const char *fmt, ...)
 {
@@ -282,7 +228,7 @@ tcp_sendf (server *serv, const char *fmt, ...)
 	int len;
 
 	va_start (args, fmt);
-	len = vsnprintf (send_buf, sizeof (send_buf) - 1, fmt, args);
+	len = g_vsnprintf (send_buf, sizeof (send_buf) - 1, fmt, args);
 	va_end (args);
 
 	send_buf[sizeof (send_buf) - 1] = '\0';
@@ -309,103 +255,17 @@ close_socket (int sok)
 /* handle 1 line of text received from the server */
 
 static void
-server_inline (server *serv, char *line, int len)
+server_inline (server *serv, char *line, gssize len)
 {
-	char *utf_line_allocated = NULL;
-
-	/* Checks whether we're set to use UTF-8 charset */
-	if (serv->using_irc ||				/* 1. using CP1252/UTF-8 Hybrid */
-		(serv->encoding == NULL && prefs.utf8_locale) || /* OR 2. using system default->UTF-8 */
-	    (serv->encoding != NULL &&				/* OR 3. explicitly set to UTF-8 */
-		 (g_ascii_strcasecmp (serv->encoding, "UTF8") == 0 ||
-		  g_ascii_strcasecmp (serv->encoding, "UTF-8") == 0)))
-	{
-		/* The user has the UTF-8 charset set, either via /charset
-		command or from his UTF-8 locale. Thus, we first try the
-		UTF-8 charset, and if we fail to convert, we assume
-		it to be ISO-8859-1 (see text_validate). */
-
-		utf_line_allocated = text_validate (&line, &len);
-
-	} else
-	{
-		/* Since the user has an explicit charset set, either
-		via /charset command or from his non-UTF8 locale,
-		we don't fallback to ISO-8859-1 and instead try to remove
-		errnoeous octets till the string is convertable in the
-		said charset. */
+	gsize len_utf8;
+	line = text_convert_invalid (line, len, serv->read_converter, unicode_fallback_string, &len_utf8);
 
-		const char *encoding = NULL;
-
-		if (serv->encoding != NULL)
-			encoding = serv->encoding;
-		else
-			g_get_charset (&encoding);
-
-		if (encoding != NULL)
-		{
-			char *conv_line; /* holds a copy of the original string */
-			int conv_len; /* tells g_convert how much of line to convert */
-			gsize utf_len;
-			gsize read_len;
-			GError *err;
-			gboolean retry;
-
-			conv_line = g_malloc (len + 1);
-			memcpy (conv_line, line, len);
-			conv_line[len] = 0;
-			conv_len = len;
-
-			/* if CP1255, convert it with the NUL terminator.
-				Works around SF bug #1122089 */
-			if (serv->using_cp1255)
-				conv_len++;
-
-			do
-			{
-				err = NULL;
-				retry = FALSE;
-				utf_line_allocated = g_convert_with_fallback (conv_line, conv_len, "UTF-8", encoding, "?", &read_len, &utf_len, &err);
-				if (err != NULL)
-				{
-					if (err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE && conv_len > (read_len + 1))
-					{
-						/* Make our best bet by removing the erroneous char.
-						   This will work for casual 8-bit strings with non-standard chars. */
-						memmove (conv_line + read_len, conv_line + read_len + 1, conv_len - read_len -1);
-						conv_len--;
-						retry = TRUE;
-					}
-					g_error_free (err);
-				}
-			} while (retry);
-
-			g_free (conv_line);
-
-			/* If any conversion has occured at all. Conversion might fail
-			due to errors other than invalid sequences, e.g. unknown charset. */
-			if (utf_line_allocated != NULL)
-			{
-				line = utf_line_allocated;
-				len = utf_len;
-				if (serv->using_cp1255 && len > 0)
-					len--;
-			}
-			else
-			{
-				/* If all fails, treat as UTF-8 with fallback to ISO-8859-1. */
-				utf_line_allocated = text_validate (&line, &len);
-			}
-		}
-	}
-
-	fe_add_rawlog (serv, line, len, FALSE);
+	fe_add_rawlog (serv, line, len_utf8, FALSE);
 
 	/* let proto-irc.c handle it */
-	serv->p_inline (serv, line, len);
+	serv->p_inline (serv, line, len_utf8);
 
-	if (utf_line_allocated != NULL) /* only if a special copy was allocated */
-		g_free (utf_line_allocated);
+	g_free (line);
 }
 
 /* read data from socket */
@@ -529,7 +389,7 @@ server_close_pipe (int *pipefd)	/* see comments below */
 {
 	close (pipefd[0]);	/* close WRITE end first to cause an EOF on READ */
 	close (pipefd[1]);	/* in giowin32, and end that thread. */
-	free (pipefd);
+	g_free (pipefd);
 	return FALSE;
 }
 
@@ -562,7 +422,7 @@ server_stopconnecting (server * serv)
 
 	{
 		/* if we close the pipe now, giowin32 will crash. */
-		int *pipefd = malloc (sizeof (int) * 2);
+		int *pipefd = g_new (int, 2);
 		pipefd[0] = serv->childwrite;
 		pipefd[1] = serv->childread;
 		g_idle_add ((GSourceFunc)server_close_pipe, pipefd);
@@ -593,7 +453,7 @@ ssl_cb_info (SSL * s, int where, int ret)
 
 	return;							  /* FIXME: make debug level adjustable in serverlist or settings */
 
-/*	snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
+/*	g_snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
 	if (g_sess)
 		EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
 	else
@@ -613,9 +473,9 @@ ssl_cb_verify (int ok, X509_STORE_CTX * ctx)
 	X509_NAME_oneline (X509_get_issuer_name (ctx->current_cert), issuer,
 							 sizeof (issuer));
 
-	snprintf (buf, sizeof (buf), "* Subject: %s", subject);
+	g_snprintf (buf, sizeof (buf), "* Subject: %s", subject);
 	EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
-	snprintf (buf, sizeof (buf), "* Issuer: %s", issuer);
+	g_snprintf (buf, sizeof (buf), "* Issuer: %s", issuer);
 	EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
 
 	return (TRUE);					  /* always ok */
@@ -627,6 +487,10 @@ ssl_do_connect (server * serv)
 	char buf[128];
 
 	g_sess = serv->server_session;
+
+	/* Set SNI hostname before connect */
+	SSL_set_tlsext_host_name(serv->ssl, serv->hostname);
+
 	if (SSL_connect (serv->ssl) <= 0)
 	{
 		char err_buf[128];
@@ -636,7 +500,7 @@ ssl_do_connect (server * serv)
 		if ((err = ERR_get_error ()) > 0)
 		{
 			ERR_error_string (err, err_buf);
-			snprintf (buf, sizeof (buf), "(%d) %s", err, err_buf);
+			g_snprintf (buf, sizeof (buf), "(%d) %s", err, err_buf);
 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL,
 							 NULL, NULL, 0);
 
@@ -662,59 +526,59 @@ ssl_do_connect (server * serv)
 
 		if (!_SSL_get_cert_info (&cert_info, serv->ssl))
 		{
-			snprintf (buf, sizeof (buf), "* Certification info:");
+			g_snprintf (buf, sizeof (buf), "* Certification info:");
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
-			snprintf (buf, sizeof (buf), "  Subject:");
+			g_snprintf (buf, sizeof (buf), "  Subject:");
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 			for (i = 0; cert_info.subject_word[i]; i++)
 			{
-				snprintf (buf, sizeof (buf), "    %s", cert_info.subject_word[i]);
+				g_snprintf (buf, sizeof (buf), "    %s", cert_info.subject_word[i]);
 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 								 NULL, 0);
 			}
-			snprintf (buf, sizeof (buf), "  Issuer:");
+			g_snprintf (buf, sizeof (buf), "  Issuer:");
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 			for (i = 0; cert_info.issuer_word[i]; i++)
 			{
-				snprintf (buf, sizeof (buf), "    %s", cert_info.issuer_word[i]);
+				g_snprintf (buf, sizeof (buf), "    %s", cert_info.issuer_word[i]);
 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 								 NULL, 0);
 			}
-			snprintf (buf, sizeof (buf), "  Public key algorithm: %s (%d bits)",
+			g_snprintf (buf, sizeof (buf), "  Public key algorithm: %s (%d bits)",
 						 cert_info.algorithm, cert_info.algorithm_bits);
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 			/*if (cert_info.rsa_tmp_bits)
 			{
-				snprintf (buf, sizeof (buf),
+				g_snprintf (buf, sizeof (buf),
 							 "  Public key algorithm uses ephemeral key with %d bits",
 							 cert_info.rsa_tmp_bits);
 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 								 NULL, 0);
 			}*/
-			snprintf (buf, sizeof (buf), "  Sign algorithm %s",
+			g_snprintf (buf, sizeof (buf), "  Sign algorithm %s",
 						 cert_info.sign_algorithm/*, cert_info.sign_algorithm_bits*/);
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
-			snprintf (buf, sizeof (buf), "  Valid since %s to %s",
+			g_snprintf (buf, sizeof (buf), "  Valid since %s to %s",
 						 cert_info.notbefore, cert_info.notafter);
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 		} else
 		{
-			snprintf (buf, sizeof (buf), " * No Certificate");
+			g_snprintf (buf, sizeof (buf), " * No Certificate");
 			EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 		}
 
 		chiper_info = _SSL_get_cipher_info (serv->ssl);	/* static buffer */
-		snprintf (buf, sizeof (buf), "* Cipher info:");
+		g_snprintf (buf, sizeof (buf), "* Cipher info:");
 		EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL,
 						 0);
-		snprintf (buf, sizeof (buf), "  Version: %s, cipher %s (%u bits)",
+		g_snprintf (buf, sizeof (buf), "  Version: %s, cipher %s (%u bits)",
 					 chiper_info->version, chiper_info->chiper,
 					 chiper_info->chiper_bits);
 		EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL,
@@ -724,9 +588,22 @@ ssl_do_connect (server * serv)
 		switch (verify_error)
 		{
 		case X509_V_OK:
-			/* snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
+			{
+				X509 *cert = SSL_get_peer_certificate (serv->ssl);
+				int hostname_err;
+				if ((hostname_err = _SSL_check_hostname(cert, serv->hostname)) != 0)
+				{
+					g_snprintf (buf, sizeof (buf), "* Verify E: Failed to validate hostname? (%d)%s",
+							 hostname_err, serv->accept_invalid_cert ? " -- Ignored" : "");
+					if (serv->accept_invalid_cert)
+						EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0);
+					else
+						goto conn_fail;
+				}
+				break;
+			}
+			/* g_snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
 			/* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
-			break;
 		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
 		case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
 		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
@@ -734,7 +611,7 @@ ssl_do_connect (server * serv)
 		case X509_V_ERR_CERT_HAS_EXPIRED:
 			if (serv->accept_invalid_cert)
 			{
-				snprintf (buf, sizeof (buf), "* Verify E: %s.? (%d) -- Ignored",
+				g_snprintf (buf, sizeof (buf), "* Verify E: %s.? (%d) -- Ignored",
 							 X509_verify_cert_error_string (verify_error),
 							 verify_error);
 				EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
@@ -742,9 +619,10 @@ ssl_do_connect (server * serv)
 				break;
 			}
 		default:
-			snprintf (buf, sizeof (buf), "%s.? (%d)",
+			g_snprintf (buf, sizeof (buf), "%s.? (%d)",
 						 X509_verify_cert_error_string (verify_error),
 						 verify_error);
+conn_fail:
 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL, NULL,
 							 NULL, 0);
 
@@ -763,7 +641,7 @@ ssl_do_connect (server * serv)
 	{
 		if (serv->ssl->session && serv->ssl->session->time + SSLTMOUT < time (NULL))
 		{
-			snprintf (buf, sizeof (buf), "SSL handshake timed out");
+			g_snprintf (buf, sizeof (buf), "SSL handshake timed out");
 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL,
 							 NULL, NULL, 0);
 			server_cleanup (serv); /* ->connecting = FALSE */
@@ -861,8 +739,8 @@ server_connect_success (server *serv)
 
 		/* it'll be a memory leak, if connection isn't terminated by
 		   server_cleanup() */
-		serv->ssl = _SSL_socket (ctx, serv->sok);
-		if ((err = _SSL_set_verify (ctx, ssl_cb_verify, NULL)))
+		serv->ssl = _SSL_socket (serv->ctx, serv->sok);
+		if ((err = _SSL_set_verify (serv->ctx, ssl_cb_verify, NULL)))
 		{
 			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, err, NULL,
 							 NULL, NULL, 0);
@@ -894,9 +772,6 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 	char outbuf[512];
 	char host[100];
 	char ip[100];
-#ifdef USE_MSPROXY
-	char *p;
-#endif
 
 	waitline2 (source, tbuf, sizeof tbuf);
 
@@ -911,12 +786,10 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 		closesocket (serv->sok4);
 		if (serv->proxy_sok4 != -1)
 			closesocket (serv->proxy_sok4);
-#ifdef USE_IPV6
 		if (serv->sok6 != -1)
 			closesocket (serv->sok6);
 		if (serv->proxy_sok6 != -1)
 			closesocket (serv->proxy_sok6);
-#endif
 		EMIT_SIGNAL (XP_TE_UKNHOST, sess, NULL, NULL, NULL, NULL, 0);
 		if (!servlist_cycle (serv))
 			if (prefs.hex_net_auto_reconnectonfail)
@@ -928,12 +801,10 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 		closesocket (serv->sok4);
 		if (serv->proxy_sok4 != -1)
 			closesocket (serv->proxy_sok4);
-#ifdef USE_IPV6
 		if (serv->sok6 != -1)
 			closesocket (serv->sok6);
 		if (serv->proxy_sok6 != -1)
 			closesocket (serv->proxy_sok6);
-#endif
 		EMIT_SIGNAL (XP_TE_CONNFAIL, sess, errorstring (atoi (tbuf)), NULL,
 						 NULL, NULL, 0);
 		if (!servlist_cycle (serv))
@@ -945,49 +816,10 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 		waitline2 (source, ip, sizeof ip);
 		waitline2 (source, outbuf, sizeof outbuf);
 		EMIT_SIGNAL (XP_TE_CONNECT, sess, host, ip, outbuf, NULL, 0);
-#ifdef WIN32
-		if (prefs.hex_identd)
-		{
-			if (serv->network && ((ircnet *)serv->network)->user)
-			{
-				identd_start (((ircnet *)serv->network)->user);
-			}
-			else
-			{
-				identd_start (prefs.hex_irc_user_name);
-			}
-		}
-#else
-		snprintf (outbuf, sizeof (outbuf), "%s/auth/xchat_auth",
-					 g_get_home_dir ());
-		if (access (outbuf, X_OK) == 0)
-		{
-			snprintf (outbuf, sizeof (outbuf), "exec -d %s/auth/xchat_auth %s",
-						 g_get_home_dir (), prefs.hex_irc_user_name);
-			handle_command (serv->server_session, outbuf, FALSE);
-		}
-#endif
 		break;
 	case '4':						  /* success */
 		waitline2 (source, tbuf, sizeof (tbuf));
-#ifdef USE_MSPROXY
-		serv->sok = strtol (tbuf, &p, 10);
-		if (*p++ == ' ')
-		{
-			serv->proxy_sok = strtol (p, &p, 10);
-			serv->msp_state.clientid = strtol (++p, &p, 10);
-			serv->msp_state.serverid = strtol (++p, &p, 10);
-			serv->msp_state.seq_sent = atoi (++p);
-		} else
-			serv->proxy_sok = -1;
-#ifdef DEBUG_MSPROXY
-		printf ("Parent got main socket: %d, proxy socket: %d\n", serv->sok, serv->proxy_sok);
-		printf ("Client ID 0x%08x server ID 0x%08x seq_sent %d\n", serv->msp_state.clientid, serv->msp_state.serverid, serv->msp_state.seq_sent);
-#endif
-#else
 		serv->sok = atoi (tbuf);
-#endif
-#ifdef USE_IPV6
 		/* close the one we didn't end up using */
 		if (serv->sok == serv->sok4)
 			closesocket (serv->sok6);
@@ -1000,7 +832,29 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 			else
 				closesocket (serv->proxy_sok4);
 		}
-#endif
+
+		{
+			struct sockaddr addr;
+			int addr_len = sizeof (addr);
+			guint16 port;
+
+			if (!getsockname (serv->sok, &addr, &addr_len))
+			{
+				if (addr.sa_family == AF_INET)
+					port = ntohs(((struct sockaddr_in *)&addr)->sin_port);
+				else
+					port = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port);
+
+				g_snprintf (outbuf, sizeof (outbuf), "IDENTD %"G_GUINT16_FORMAT" ", port);
+				if (serv->network && ((ircnet *)serv->network)->user)
+					g_strlcat (outbuf, ((ircnet *)serv->network)->user, sizeof (outbuf));
+				else
+					g_strlcat (outbuf, prefs.hex_irc_user_name, sizeof (outbuf));
+
+				handle_command (serv->server_session, outbuf, FALSE);
+			}
+		}
+
 		server_connect_success (serv);
 		break;
 	case '5':						  /* prefs ip discovered */
@@ -1186,7 +1040,7 @@ traverse_socks (int print_fd, int sok, char *serverAddr, int port)
 	if (buf[1] == 90)
 		return 0;
 
-	snprintf (buf, sizeof (buf), "SOCKS\tServer reported error %d,%d.\n", buf[0], buf[1]);
+	g_snprintf (buf, sizeof (buf), "SOCKS\tServer reported error %d,%d.\n", buf[0], buf[1]);
 	proxy_error (print_fd, buf);
 	return 1;
 }
@@ -1270,7 +1124,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
 
 	addrlen = strlen (serverAddr);
 	packetlen = 4 + 1 + addrlen + 2;
-	sc2 = malloc (packetlen);
+	sc2 = g_malloc (packetlen);
 	sc2[0] = 5;						  /* version */
 	sc2[1] = 1;						  /* command */
 	sc2[2] = 0;						  /* reserved */
@@ -1279,7 +1133,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
 	memcpy (sc2 + 5, serverAddr, addrlen);
 	*((unsigned short *) (sc2 + 5 + addrlen)) = htons (port);
 	send (sok, sc2, packetlen, 0);
-	free (sc2);
+	g_free (sc2);
 
 	/* consume all of the reply */
 	if (recv (sok, buf, 4, 0) != 4)
@@ -1287,9 +1141,9 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
 	if (buf[0] != 5 || buf[1] != 0)
 	{
 		if (buf[1] == 2)
-			snprintf (buf, sizeof (buf), "SOCKS\tProxy refused to connect to host (not allowed).\n");
+			g_snprintf (buf, sizeof (buf), "SOCKS\tProxy refused to connect to host (not allowed).\n");
 		else
-			snprintf (buf, sizeof (buf), "SOCKS\tProxy failed to connect to host (error %d).\n", buf[1]);
+			g_snprintf (buf, sizeof (buf), "SOCKS\tProxy failed to connect to host (error %d).\n", buf[1]);
 		proxy_error (print_fd, buf);
 		return 1;
 	}
@@ -1322,7 +1176,7 @@ traverse_wingate (int print_fd, int sok, char *serverAddr, int port)
 {
 	char buf[128];
 
-	snprintf (buf, sizeof (buf), "%s %d\r\n", serverAddr, port);
+	g_snprintf (buf, sizeof (buf), "%s %d\r\n", serverAddr, port);
 	send (sok, buf, strlen (buf), 0);
 
 	return 0;
@@ -1410,16 +1264,16 @@ traverse_http (int print_fd, int sok, char *serverAddr, int port)
 	char auth_data2[252];
 	int n, n2;
 
-	n = snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
+	n = g_snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
 					  serverAddr, port);
 	if (prefs.hex_net_proxy_auth)
 	{
-		n2 = snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
+		n2 = g_snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
 							prefs.hex_net_proxy_user, prefs.hex_net_proxy_pass);
 		base64_encode (auth_data, auth_data2, n2);
-		n += snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
+		n += g_snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
 	}
-	n += snprintf (buf+n, sizeof (buf)-n, "\r\n");
+	n += g_snprintf (buf+n, sizeof (buf)-n, "\r\n");
 	send (sok, buf, n, 0);
 
 	n = http_read_line (print_fd, sok, buf, sizeof (buf));
@@ -1439,7 +1293,7 @@ traverse_http (int print_fd, int sok, char *serverAddr, int port)
 }
 
 static int
-traverse_proxy (int proxy_type, int print_fd, int sok, char *ip, int port, struct msproxy_state_t *state, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound)
+traverse_proxy (int proxy_type, int print_fd, int sok, char *ip, int port, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound)
 {
 	switch (proxy_type)
 	{
@@ -1451,10 +1305,6 @@ traverse_proxy (int proxy_type, int print_fd, int sok, char *ip, int port, struc
 		return traverse_socks5 (print_fd, sok, ip, port);
 	case 4:
 		return traverse_http (print_fd, sok, ip, port);
-#ifdef USE_MSPROXY
-	case 5:
-		return traverse_msproxy (sok, ip, port, state, ns_proxy, csok4, csok6, csok, bound);
-#endif
 	}
 
 	return 1;
@@ -1492,7 +1342,7 @@ server_child (server * serv)
 		local_ip = net_resolve (ns_local, prefs.hex_net_bind_host, 0, &real_hostname);
 		if (local_ip != NULL)
 		{
-			snprintf (buf, sizeof (buf), "5\n%s\n", local_ip);
+			g_snprintf (buf, sizeof (buf), "5\n%s\n", local_ip);
 			write (serv->childwrite, buf, strlen (buf));
 			net_bind (ns_local, serv->sok4, serv->sok6);
 			bound = 1;
@@ -1505,10 +1355,8 @@ server_child (server * serv)
 
 	if (!serv->dont_use_proxy) /* blocked in serverlist? */
 	{
-		if (FALSE)
-			;
 #ifdef USE_LIBPROXY
-		else if (prefs.hex_net_proxy_type == 5)
+		if (prefs.hex_net_proxy_type == 5)
 		{
 			char **proxy_list;
 			char *url, *proxy;
@@ -1532,7 +1380,7 @@ server_child (server * serv)
 			if (proxy_type) {
 				char *c;
 				c = strchr (proxy, ':') + 3;
-				proxy_host = strdup (c);
+				proxy_host = g_strdup (c);
 				c = strchr (proxy_host, ':');
 				*c = '\0';
 				proxy_port = atoi (c + 1);
@@ -1542,12 +1390,12 @@ server_child (server * serv)
 			g_free (url);
 		}
 #endif
-		else if (prefs.hex_net_proxy_host[0] &&
+		if (prefs.hex_net_proxy_host[0] &&
 			   prefs.hex_net_proxy_type > 0 &&
 			   prefs.hex_net_proxy_use != 2) /* proxy is NOT dcc-only */
 		{
 			proxy_type = prefs.hex_net_proxy_type;
-			proxy_host = strdup (prefs.hex_net_proxy_host);
+			proxy_host = g_strdup (prefs.hex_net_proxy_host);
 			proxy_port = prefs.hex_net_proxy_port;
 		}
 	}
@@ -1557,10 +1405,10 @@ server_child (server * serv)
 	/* first resolve where we want to connect to */
 	if (proxy_type > 0)
 	{
-		snprintf (buf, sizeof (buf), "9\n%s\n", proxy_host);
+		g_snprintf (buf, sizeof (buf), "9\n%s\n", proxy_host);
 		write (serv->childwrite, buf, strlen (buf));
 		ip = net_resolve (ns_server, proxy_host, proxy_port, &real_hostname);
-		free (proxy_host);
+		g_free (proxy_host);
 		if (!ip)
 		{
 			write (serv->childwrite, "1\n", 2);
@@ -1579,7 +1427,7 @@ server_child (server * serv)
 				goto xit;
 			}
 		} else						  /* otherwise we can just use the hostname */
-			proxy_ip = strdup (hostname);
+			proxy_ip = g_strdup (hostname);
 	} else
 	{
 		ip = net_resolve (ns_server, hostname, port, &real_hostname);
@@ -1591,7 +1439,7 @@ server_child (server * serv)
 		connect_port = port;
 	}
 
-	snprintf (buf, sizeof (buf), "3\n%s\n%s\n%d\n",
+	g_snprintf (buf, sizeof (buf), "3\n%s\n%s\n%d\n",
 				 real_hostname, ip, connect_port);
 	write (serv->childwrite, buf, strlen (buf));
 
@@ -1605,23 +1453,17 @@ server_child (server * serv)
 
 	if (error != 0)
 	{
-		snprintf (buf, sizeof (buf), "2\n%d\n", sock_error ());
+		g_snprintf (buf, sizeof (buf), "2\n%d\n", sock_error ());
 		write (serv->childwrite, buf, strlen (buf));
 	} else
 	{
 		/* connect succeeded */
 		if (proxy_ip)
 		{
-			switch (traverse_proxy (proxy_type, serv->childwrite, psok, proxy_ip, port, &serv->msp_state, ns_proxy, serv->sok4, serv->sok6, &sok, bound))
+			switch (traverse_proxy (proxy_type, serv->childwrite, psok, proxy_ip, port, ns_proxy, serv->sok4, serv->sok6, &sok, bound))
 			{
 			case 0:	/* success */
-#ifdef USE_MSPROXY
-				if (!serv->dont_use_proxy && (proxy_type == 5))
-					snprintf (buf, sizeof (buf), "4\n%d %d %d %d %d\n", sok, psok, serv->msp_state.clientid, serv->msp_state.serverid,
-						serv->msp_state.seq_sent);
-				else
-#endif
-					snprintf (buf, sizeof (buf), "4\n%d\n", sok);	/* success */
+				g_snprintf (buf, sizeof (buf), "4\n%d\n", sok);	/* success */
 				write (serv->childwrite, buf, strlen (buf));
 				break;
 			case 1:	/* socks traversal failed */
@@ -1630,29 +1472,24 @@ server_child (server * serv)
 			}
 		} else
 		{
-			snprintf (buf, sizeof (buf), "4\n%d\n", sok);	/* success */
+			g_snprintf (buf, sizeof (buf), "4\n%d\n", sok);	/* success */
 			write (serv->childwrite, buf, strlen (buf));
 		}
 	}
 
 xit:
 
-#if defined (USE_IPV6) || defined (WIN32)
 	/* this is probably not needed */
 	net_store_destroy (ns_server);
 	if (ns_proxy)
 		net_store_destroy (ns_proxy);
-#endif
 
 	/* no need to free ip/real_hostname, this process is exiting */
 #ifdef WIN32
 	/* under win32 we use a thread -> shared memory, must free! */
-	if (proxy_ip)
-		free (proxy_ip);
-	if (ip)
-		free (ip);
-	if (real_hostname)
-		free (real_hostname);
+	g_free (proxy_ip);
+	g_free (ip);
+	g_free (real_hostname);
 #endif
 
 	return 0;
@@ -1666,9 +1503,9 @@ server_connect (server *serv, char *hostname, int port, int no_login)
 	session *sess = serv->server_session;
 
 #ifdef USE_OPENSSL
-	if (!ctx && serv->use_ssl)
+	if (!serv->ctx && serv->use_ssl)
 	{
-		if (!(ctx = _SSL_context_init (ssl_cb_info, FALSE)))
+		if (!(serv->ctx = _SSL_context_init (ssl_cb_info)))
 		{
 			fprintf (stderr, "_SSL_context_init failed\n");
 			exit (1);
@@ -1711,18 +1548,18 @@ server_connect (server *serv, char *hostname, int port, int no_login)
 		/* first try network specific cert/key */
 		cert_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "certs" G_DIR_SEPARATOR_S "%s.pem",
 					 get_xdir (), server_get_network (serv, TRUE));
-		if (SSL_CTX_use_certificate_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
+		if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
 		{
-			if (SSL_CTX_use_PrivateKey_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
+			if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
 				serv->have_cert = TRUE;
 		}
 		else
 		{
 			/* if that doesn't exist, try <config>/certs/client.pem */
 			cert_file = g_build_filename (get_xdir (), "certs", "client.pem", NULL);
-			if (SSL_CTX_use_certificate_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
+			if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
 			{
-				if (SSL_CTX_use_PrivateKey_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
+				if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
 					serv->have_cert = TRUE;
 			}
 		}
@@ -1754,16 +1591,8 @@ server_connect (server *serv, char *hostname, int port, int no_login)
 
 	/* create both sockets now, drop one later */
 	net_sockets (&serv->sok4, &serv->sok6);
-#ifdef USE_MSPROXY
-	/* In case of MS Proxy we have a separate UDP control connection */
-	if (!serv->dont_use_proxy && (serv->proxy_type == 5))
-		udp_sockets (&serv->proxy_sok4, &serv->proxy_sok6);
-	else
-#endif
-	{
-		serv->proxy_sok4 = -1;
-		serv->proxy_sok6 = -1;
-	}
+	serv->proxy_sok4 = -1;
+	serv->proxy_sok6 = -1;
 
 #ifdef WIN32
 	CloseHandle (CreateThread (NULL, 0,
@@ -1815,31 +1644,46 @@ server_set_encoding (server *serv, char *new_encoding)
 {
 	char *space;
 
-	if (serv->encoding)
-	{
-		free (serv->encoding);
-		/* can be left as NULL to indicate system encoding */
-		serv->encoding = NULL;
-		serv->using_cp1255 = FALSE;
-		serv->using_irc = FALSE;
-	}
+	g_free (serv->encoding);
 
 	if (new_encoding)
 	{
-		serv->encoding = strdup (new_encoding);
+		serv->encoding = g_strdup (new_encoding);
 		/* the serverlist GUI might have added a space 
 			and short description - remove it. */
 		space = strchr (serv->encoding, ' ');
 		if (space)
 			space[0] = 0;
 
-		/* server_inline() uses these flags */
-		if (!g_ascii_strcasecmp (serv->encoding, "CP1255") ||
-			 !g_ascii_strcasecmp (serv->encoding, "WINDOWS-1255"))
-			serv->using_cp1255 = TRUE;
-		else if (!g_ascii_strcasecmp (serv->encoding, "IRC"))
-			serv->using_irc = TRUE;
+		/* Default legacy "IRC" encoding to utf-8. */
+		if (g_ascii_strcasecmp (serv->encoding, "IRC") == 0)
+		{
+			g_free (serv->encoding);
+			serv->encoding = g_strdup ("UTF-8");
+		}
+
+		else if (!servlist_check_encoding (serv->encoding))
+		{
+			g_free (serv->encoding);
+			serv->encoding = g_strdup ("UTF-8");
+		}
+	}
+	else
+	{
+		serv->encoding = g_strdup ("UTF-8");
+	}
+
+	if (serv->read_converter != NULL)
+	{
+		g_iconv_close (serv->read_converter);
 	}
+	serv->read_converter = g_iconv_open ("UTF-8", serv->encoding);
+
+	if (serv->write_converter != NULL)
+	{
+		g_iconv_close (serv->write_converter);
+	}
+	serv->write_converter = g_iconv_open (serv->encoding, "UTF-8");
 }
 
 server *
@@ -1848,8 +1692,7 @@ server_new (void)
 	static int id = 0;
 	server *serv;
 
-	serv = malloc (sizeof (struct server));
-	memset (serv, 0, sizeof (struct server));
+	serv = g_new0 (struct server, 1);
 
 	/* use server.c and proto-irc.c functions */
 	server_fill_her_up (serv);
@@ -1875,19 +1718,17 @@ is_server (server *serv)
 void
 server_set_defaults (server *serv)
 {
-	if (serv->chantypes)
-		free (serv->chantypes);
-	if (serv->chanmodes)
-		free (serv->chanmodes);
-	if (serv->nick_prefixes)
-		free (serv->nick_prefixes);
-	if (serv->nick_modes)
-		free (serv->nick_modes);
-
-	serv->chantypes = strdup ("#&!+");
-	serv->chanmodes = strdup ("beI,k,l");
-	serv->nick_prefixes = strdup ("@%+");
-	serv->nick_modes = strdup ("ohv");
+	g_free (serv->chantypes);
+	g_free (serv->chanmodes);
+	g_free (serv->nick_prefixes);
+	g_free (serv->nick_modes);
+
+	serv->chantypes = g_strdup ("#&!+");
+	serv->chanmodes = g_strdup ("beI,k,l");
+	serv->nick_prefixes = g_strdup ("@%+");
+	serv->nick_modes = g_strdup ("ohv");
+
+	server_set_encoding (serv, "UTF-8");
 
 	serv->nickcount = 1;
 	serv->end_of_motd = FALSE;
@@ -1991,9 +1832,8 @@ server_away_free_messages (server *serv)
 		if (away->server == serv)
 		{
 			away_list = g_slist_remove (away_list, away);
-			if (away->message)
-				free (away->message);
-			free (away);
+			g_free (away->message);
+			g_free (away);
 			next = away_list;
 		}
 		list = next;
@@ -2007,20 +1847,17 @@ server_away_save_message (server *serv, char *nick, char *msg)
 
 	if (away)						  /* Change message for known user */
 	{
-		if (away->message)
-			free (away->message);
-		away->message = strdup (msg);
-	} else
-		/* Create brand new entry */
+		g_free (away->message);
+		away->message = g_strdup (msg);
+	}
+	else
 	{
-		away = malloc (sizeof (struct away_msg));
-		if (away)
-		{
-			away->server = serv;
-			safe_strcpy (away->nick, nick, sizeof (away->nick));
-			away->message = strdup (msg);
-			away_list = g_slist_prepend (away_list, away);
-		}
+		/* Create brand new entry */
+		away = g_new(struct away_msg, 1);
+		away->server = serv;
+		safe_strcpy (away->nick, nick, sizeof (away->nick));
+		away->message = g_strdup (msg);
+		away_list = g_slist_prepend (away_list, away);
 	}
 }
 
@@ -2035,22 +1872,27 @@ server_free (server *serv)
 	serv->flush_queue (serv);
 	server_away_free_messages (serv);
 
-	free (serv->nick_modes);
-	free (serv->nick_prefixes);
-	free (serv->chanmodes);
-	free (serv->chantypes);
-	if (serv->bad_nick_prefixes)
-		free (serv->bad_nick_prefixes);
-	if (serv->last_away_reason)
-		free (serv->last_away_reason);
-	if (serv->encoding)
-		free (serv->encoding);
+	g_free (serv->nick_modes);
+	g_free (serv->nick_prefixes);
+	g_free (serv->chanmodes);
+	g_free (serv->chantypes);
+	g_free (serv->bad_nick_prefixes);
+	g_free (serv->last_away_reason);
+	g_free (serv->encoding);
+
+	g_iconv_close (serv->read_converter);
+	g_iconv_close (serv->write_converter);
+
 	if (serv->favlist)
 		g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free);
+#ifdef USE_OPENSSL
+	if (serv->ctx)
+		_SSL_context_free (serv->ctx);
+#endif
 
 	fe_server_callback (serv);
 
-	free (serv);
+	g_free (serv);
 
 	notify_cleanup ();
 }
diff --git a/src/common/server.h b/src/common/server.h
index 90e9a9c1..ff8ef404 100644
--- a/src/common/server.h
+++ b/src/common/server.h
@@ -24,9 +24,8 @@ extern GSList *serv_list;
 
 /* eventually need to keep the tcp_* functions isolated to server.c */
 int tcp_send_len (server *serv, char *buf, int len);
-int tcp_send (server *serv, char *buf);
 void tcp_sendf (server *serv, const char *fmt, ...) G_GNUC_PRINTF (2, 3);
-int tcp_send_real (void *ssl, int sok, char *encoding, int using_irc, char *buf, int len);
+int tcp_send_real (void *ssl, int sok, GIConv write_converter, char *buf, int len);
 
 server *server_new (void);
 int is_server (server *serv);
diff --git a/src/common/servlist.c b/src/common/servlist.c
index 7de77596..6f9f9ed2 100644
--- a/src/common/servlist.c
+++ b/src/common/servlist.c
@@ -45,6 +45,7 @@ struct defaultserver
 	char *charset;
 	int loginmode;		/* default authentication type */
 	char *connectcmd;	/* default connect command - should only be used for rare login types, paired with LOGIN_CUSTOM */
+	gboolean ssl;
 };
 
 static const struct defaultserver def[] =
@@ -59,20 +60,11 @@ static const struct defaultserver def[] =
 
 	{"AccessIRC",	0},
 	{0,			"irc.accessirc.net"},
-	{0,			"eu.accessirc.net"},
 
 	{"AfterNET",	0},
 	{0,			"irc.afternet.org"},
-	{0,			"us.afternet.org"},
-	{0,			"eu.afternet.org"},
 
 	{"Aitvaras",	0},
-#ifdef USE_IPV6
-#ifdef USE_OPENSSL
-	{0,			"irc6.ktu.lt/+7668"},
-#endif
-	{0,			"irc6.ktu.lt/7666"},
-#endif
 #ifdef USE_OPENSSL
 	{0,			"irc.data.lt/+6668"},
 	{0,			"irc.omnitel.net/+6668"},
@@ -86,52 +78,25 @@ static const struct defaultserver def[] =
 	{0,			"irc.kis.lt"},
 	{0,			"irc.vub.lt"},
 
-	{"AlphaChat",	0, 0, 0, LOGIN_SASL},
-	{0,			"irc.alphachat.net"},
-	{0,			"na.alphachat.net"},
-	{0,			"eu.alphachat.net"},
-	{0,			"au.alphachat.net"},
-	{0,			"za.alphachat.net"},
-
-	{"Anthrochat", 0},
-#ifdef USE_OPENSSL
-	{0,			"irc.anthrochat.net/+6697"},
-#endif
+	{"Anthrochat", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.anthrochat.net"},
 
 	{"ARCNet",	0},
-	{0,			"se1.arcnet.vapor.com"},
-	{0,			"us1.arcnet.vapor.com"},
-	{0,			"us2.arcnet.vapor.com"},
-	{0,			"us3.arcnet.vapor.com"},
-	{0,			"ca1.arcnet.vapor.com"},
-	{0,			"de1.arcnet.vapor.com"},
-	{0,			"de3.arcnet.vapor.com"},
-	{0,			"ch1.arcnet.vapor.com"},
-	{0,			"be1.arcnet.vapor.com"},
-	{0,			"nl3.arcnet.vapor.com"},
-	{0,			"uk1.arcnet.vapor.com"},
-	{0,			"uk2.arcnet.vapor.com"},
-	{0,			"fr1.arcnet.vapor.com"},
+	{0,			"arcnet-irc.org"},
+
+	{"AthemeNet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.atheme.org"},
 
 	{"AustNet",	0},
-	{0,			"au.austnet.org"},
-	{0,			"us.austnet.org"},
+	{0,			"irc.austnet.org"},
 
 	{"AzzurraNet",	0},
 	{0,			"irc.azzurra.org"},
-	{0,			"crypto.azzurra.org"},
 
-	{"Canternet", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0, 		"irc.canternet.org/+6697"},
-#endif
+	{"Canternet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.canternet.org"},
 
-	{"Chat4all", 0},
-#ifdef USE_OPENSSL
-	{0,			"irc.chat4all.org/+7001"},
-#endif
+	{"Chat4all", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.chat4all.org"},
 
 	{"ChattingAway", 0},
@@ -139,26 +104,21 @@ static const struct defaultserver def[] =
 
 	{"ChatJunkies",	0},
 	{0,			"irc.chatjunkies.org"},
-	{0,			"nl.chatjunkies.org"},
 
 	{"ChatNet",	0},
-	{0,			"US.ChatNet.Org"},
+	{0,			"irc.chatnet.org"},
 
 	{"ChatSpike", 0},
 	{0,			"irc.chatspike.net"},
 
 	{"Criten", 0},
 	{0,			"irc.criten.net"},
-	{0,			"irc.eu.criten.net"},
 
 	{"DALnet", 0},
 	{0,			"irc.dal.net"},
-	{0,			"irc.eu.dal.net"},
 
 	{"Dark-Tou-Net",	0},
 	{0,			"irc.d-t-net.de"},
-	{0,			"bw.d-t-net.de"},
-	{0,			"nc.d-t-net.de"},
 
 	{"DarkMyst", 0, 0, 0, LOGIN_SASL},
 	{0,			"irc.darkmyst.org"},
@@ -177,66 +137,36 @@ static const struct defaultserver def[] =
 	{0,			"irc.lightning.net"},
 	{0,			"irc.servercentral.net"},
 
-	{"ElectroCode",		0},
-#ifdef USE_OPENSSL
-
-	{0,			"irc.electrocode.net/+6697"},
-#endif
+	{"ElectroCode", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.electrocode.net"},
 
 	{"EnterTheGame",	0},
-	{0,			"IRC.EnterTheGame.Com"},
+	{0,			"irc.enterthegame.com"},
 
-	{"EntropyNet",	0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.entropynet.net/+6697"},
-#endif
+	{"EntropyNet",	0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.entropynet.net"},
-#ifdef USE_IPV6
-#ifdef USE_OPENSSL
-	{0,			"irc6.entropynet.net/+6697"},
-#endif
-	{0,			"irc6.entropynet.net"},
-#endif
 
-	{"EsperNet", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.esper.net/+6697"},
-#endif
+	{"EsperNet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.esper.net"},
 
 	{"EUIrc",	0},
 	{0,			"irc.euirc.net"},
-	{0,			"irc.ham.de.euirc.net"},
-	{0,			"irc.ber.de.euirc.net"},
-	{0,			"irc.ffm.de.euirc.net"},
-	{0,			"irc.bre.de.euirc.net"},
-	{0,			"irc.hes.de.euirc.net"},
-	{0,			"irc.inn.at.euirc.net"},
-	{0,			"irc.bas.ch.euirc.net"},
 
 	{"EuropNet", 0},
 	{0,			"irc.europnet.org"},
 
 	{"FDFNet",	0},
 	{0,			"irc.fdfnet.net"},
-	{0,			"irc.eu.fdfnet.net"},
 
 	{"FEFNet", 0, 0, 0, LOGIN_SASL},
 	{0,			"irc.fef.net"},
 
-	{"freenode", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,				"chat.freenode.net/+6697"},
-#endif
+	{"freenode", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,				"chat.freenode.net"},
 	/* irc. points to chat. but many users and urls still reference it */
 	{0,				"irc.freenode.net"},
 
-	{"Furnet",	0},
-#ifdef USE_OPENSSL
-	{0,			"irc.furnet.org/+6697"},
-#endif
+	{"Furnet", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.furnet.org"},
 
 	{"GalaxyNet",	0},
@@ -245,18 +175,14 @@ static const struct defaultserver def[] =
 	{"GameSurge", 0},
 	{0,			"irc.gamesurge.net"},
 	
-	{"GeeksIRC", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.geeksirc.net/+6697"},
-#endif
+	{"GeeksIRC", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.geeksirc.net"},
 
 	{"GeekShed",	0},
 	{0,			"irc.geekshed.net"},
 
 	{"German-Elite",	0},
-	{0,			"dominion.german-elite.net"},
-	{0,			"komatu.german-elite.net"},
+	{0,			"irc.german-elite.net"},
 
 	{"GIMPNet",		0},
 	{0,			"irc.gimp.org"},
@@ -268,22 +194,13 @@ static const struct defaultserver def[] =
 	{"IdleMonkeys", 0},
 	{0,			"irc.idlemonkeys.net"},
 
-	{"IndirectIRC", 0},
-#ifdef USE_OPENSSL
-	{0,			"irc.indirectirc.com/+6697"},
-#endif
+	{"IndirectIRC", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.indirectirc.com"},
 	
-	{"Interlinked", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.interlinked.me/+6697"},
-#endif
+	{"Interlinked", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.interlinked.me"},
 
-	{"IRC4Fun", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,				"irc.irc4fun.net/+6697"},
-#endif
+	{"IRC4Fun", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,				"irc.irc4fun.net"},
 
 	{"IRCHighWay",	0},
@@ -294,28 +211,15 @@ static const struct defaultserver def[] =
 
 	{"IrcLink",	0},
 	{0,			"irc.irclink.net"},
-	{0,			"Alesund.no.eu.irclink.net"},
-	{0,			"Oslo.no.eu.irclink.net"},
-	{0,			"frogn.no.eu.irclink.net"},
-	{0,			"tonsberg.no.eu.irclink.net"},
 
 	{"IRCNet",		0},
 	{0,				"open.ircnet.net"},
-	{0,				"irc.de.ircnet.net"},
-	
-	{"IRCNode", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.ircnode.org/+6697"},
-#endif
-	{0,                     "irc.ircnode.org"},
 
 	{"Irctoo.net",	0},
 	{0,			"irc.irctoo.net"},
 
 	{"iZ-smart.net",	0},
-	{0,			"irc.iZ-smart.net/6666"},
-	{0,			"irc.iZ-smart.net/6667"},
-	{0,			"irc.iZ-smart.net/6668"},
+	{0,			"irc.iz-smart.net"},
 
 	{"Krstarica", 0},
 	{0,			"irc.krstarica.com"},
@@ -323,12 +227,6 @@ static const struct defaultserver def[] =
 #ifdef USE_OPENSSL
 	{"LinkNet",	0},
 	{0,			"irc.link-net.org/+7000"},
-	{0,			"as.link-net.org/+7000"},
-	{0,			"eu.link-net.org/+7000"},
-	{0,			"us.link-net.org/+7000"},
-#ifdef USE_IPV6
-	{0,			"irc6.link-net.org/+7000"},
-#endif
 #endif
 
 	{"MindForge",	0},
@@ -358,31 +256,14 @@ static const struct defaultserver def[] =
 	{"PIRC.PL",	0},
 	{0,			"irc.pirc.pl"},
 	
-	{"PonyChat", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0, 		"irc.ponychat.net/+6697"},
-#endif
+	{"PonyChat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.ponychat.net"},
 
 	{"PTNet.org",   0},
-	{0,			"irc.PTNet.org"},
-	{0,			"world.PTnet.org"},
-	{0,			"netvisao.PTnet.org"},
-	{0,			"uevora.PTnet.org"},
-	{0,			"vianetworks.PTnet.org"},
-	{0,			"uc.PTnet.org"},
-	{0,			"nfsi.ptnet.org"},
-	{0,			"fctunl.ptnet.org"},
+	{0,			"irc.ptnet.org"},
 
 	{"QuakeNet", 0, 0, 0, LOGIN_CHALLENGEAUTH},
 	{0,			"irc.quakenet.org"},
-	{0,			"irc.se.quakenet.org"},
-	{0,			"irc.dk.quakenet.org"},
-	{0,			"irc.no.quakenet.org"},
-	{0,			"irc.fi.quakenet.org"},
-	{0,			"irc.be.quakenet.org"},
-	{0,			"irc.uk.quakenet.org"},
-	{0,			"irc.it.quakenet.org"},
 
 	{"Rizon", 0},
 	{0,			"irc.rizon.net"},
@@ -395,37 +276,21 @@ static const struct defaultserver def[] =
 
 	{"SceneNet",	0},
 	{0,			"irc.scene.org"},
-	{0,			"irc.eu.scene.org"},
-	{0,			"irc.us.scene.org"},
 
 	{"SeilEn.de",	0},
 	{0,			"irc.seilen.de"},
 
-	{"SeionIRC", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.seion.us/+6697"},
-#endif
-	{0,			"irc.seion.us"},
-
 	{"Serenity-IRC",	0},
 	{0,			"irc.serenity-irc.net"},
-	{0,			"eu.serenity-irc.net"},
-	{0,			"us.serenity-irc.net"},
 
 	{"SlashNET",	0},
 	{0,			"irc.slashnet.org"},
-	{0,			"area51.slashnet.org"},
-	{0,			"moo.slashnet.org"},
-	{0,			"radon.slashnet.org"},
 
-	{"Snoonet", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.snoonet.org/+6697"},
-#endif
-	{0,			"irc.snoonet.org/6667"},
+	{"Snoonet", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.snoonet.org"},
 
 	{"Snyde", 0},
-	{0,			"irc.snyde.net/6667"},
+	{0,			"irc.snyde.net"},
 
 	{"Sohbet.Net", 0},
 	{0,			"irc.sohbet.net"},
@@ -434,57 +299,28 @@ static const struct defaultserver def[] =
 	{0,			"irc.solidirc.com"},
 
 	{"SorceryNet", 0, 0, 0, LOGIN_SASL},
-	{0,			"irc.sorcery.net/9000"},
-	{0,			"irc.us.sorcery.net/9000"},
-	{0,			"irc.eu.sorcery.net/9000"},
+	{0,			"irc.sorcery.net"},
 	
-	{"SpotChat", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.spotchat.org/+6697"},
-#endif
-	{0,			"irc.spotchat.org/6667"},
+	{"SpotChat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.spotchat.org"},
 
 	{"StarChat", 0},
 	{0,			"irc.starchat.net"},
-	{0,			"gainesville.starchat.net"},
-	{0,			"freebsd.starchat.net"},
-	{0,			"sunset.starchat.net"},
-	{0,			"revenge.starchat.net"},
-	{0,			"tahoma.starchat.net"},
-	{0,			"neo.starchat.net"},
 
-	{"StaticBox", 0, 0, 0, LOGIN_SASL},
-	{0,			"irc.staticbox.net"},
-
-	{"Station51", 0},
-#ifdef USE_OPENSSL
-	{0,			"irc.station51.net/+6697"},
-#endif
+	{"Station51", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.station51.net"},
 
-	{"StormBit", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.stormbit.net/+6697"},
-#endif
+	{"StormBit", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.stormbit.net"},
 
-	{"SwiftIRC", 0},
-#ifdef USE_OPENSSL
-	{0,			"irc.swiftirc.net/+6697"},
-#endif
-	{0,			"irc.swiftirc.net/6667"},
+	{"SwiftIRC", 0, 0, 0, 0, 0, TRUE},
+	{0,			"irc.swiftirc.net"},
 
-	{"synIRC", 0},
-#ifdef USE_OPENSSL
-	{0, "irc.synirc.net/+6697"},
-#endif
-	{0, "irc.synirc.net/6667"},
+	{"synIRC", 0, 0, 0, 0, 0, TRUE},
+	{0, "irc.synirc.net"},
 
-	{"Techman's World IRC",	0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.techmansworld.com/+6697"},
-#endif
-	{0,			"irc.techmansworld.com/6667"},
+	{"Techtronix",	0, 0, 0, LOGIN_SASL, 0, TRUE},
+	{0,			"irc.techtronix.net"},
 
 	{"TinyCrab", 0, 0, 0, LOGIN_SASL},
 	{0,			"irc.tinycrab.net"},
@@ -508,16 +344,10 @@ static const struct defaultserver def[] =
 	{"Worldnet",		0},
 	{0,			"irc.worldnet.net"},
 
-	{"Windfyre",		0},
-#ifdef USE_OPENSSL
-	{0,			"irc.windfyre.net/+6697"},
-#endif
+	{"Windfyre", 0, 0, 0, 0, 0, TRUE},
 	{0,			"irc.windfyre.net"},
 
-	{"Xertion", 0, 0, 0, LOGIN_SASL},
-#ifdef USE_OPENSSL
-	{0,			"irc.xertion.org/+6697"},
-#endif
+	{"Xertion", 0, 0, 0, LOGIN_SASL, 0, TRUE},
 	{0,			"irc.xertion.org"},
 
 	{0,0}
@@ -566,9 +396,7 @@ servlist_favchan_copy (favchannel *fav)
 {
 	favchannel *newfav;
 
-	newfav = malloc (sizeof (favchannel));
-	memset (newfav, 0, sizeof (favchannel));
-
+	newfav = g_new (favchannel, 1);
 	newfav->name = g_strdup (fav->name);
 	newfav->key = g_strdup (fav->key);		/* g_strdup() can handle NULLs so no need to check it */
 
@@ -924,9 +752,8 @@ servlist_server_add (ircnet *net, char *name)
 {
 	ircserver *serv;
 
-	serv = malloc (sizeof (ircserver));
-	memset (serv, 0, sizeof (ircserver));
-	serv->hostname = strdup (name);
+	serv = g_new (ircserver, 1);
+	serv->hostname = g_strdup (name);
 
 	net->servlist = g_slist_append (net->servlist, serv);
 
@@ -938,9 +765,8 @@ servlist_command_add (ircnet *net, char *cmd)
 {
 	commandentry *entry;
 
-	entry = malloc (sizeof (commandentry));
-	memset (entry, 0, sizeof (commandentry));
-	entry->command = strdup (cmd);
+	entry = g_new (commandentry, 1);
+	entry->command = g_strdup (cmd);
 
 	net->commandlist = g_slist_append (net->commandlist, entry);
 
@@ -952,9 +778,7 @@ servlist_favchan_listadd (GSList *chanlist, char *channel, char *key)
 {
 	favchannel *chan;
 
-	chan = malloc (sizeof (favchannel));
-	memset (chan, 0, sizeof (favchannel));
-
+	chan = g_new (favchannel, 1);
 	chan->name = g_strdup (channel);
 	chan->key = g_strdup (key);
 	chanlist = g_slist_append (chanlist, chan);
@@ -990,8 +814,8 @@ servlist_favchan_add (ircnet *net, char *channel)
 void
 servlist_server_remove (ircnet *net, ircserver *serv)
 {
-	free (serv->hostname);
-	free (serv);
+	g_free (serv->hostname);
+	g_free (serv);
 	net->servlist = g_slist_remove (net->servlist, serv);
 }
 
@@ -1044,7 +868,7 @@ free_and_clear (char *str)
 		char *orig = str;
 		while (*str)
 			*str++ = 0;
-		free (orig);
+		g_free (orig);
 	}
 }
 
@@ -1072,25 +896,18 @@ servlist_net_remove (ircnet *net)
 	servlist_server_remove_all (net);
 	network_list = g_slist_remove (network_list, net);
 
-	if (net->nick)
-		free (net->nick);
-	if (net->nick2)
-		free (net->nick2);
-	if (net->user)
-		free (net->user);
-	if (net->real)
-		free (net->real);
+	g_free (net->nick);
+	g_free (net->nick2);
+	g_free (net->user);
+	g_free (net->real);
 	free_and_clear (net->pass);
 	if (net->favchanlist)
 		g_slist_free_full (net->favchanlist, (GDestroyNotify) servlist_favchan_free);
 	if (net->commandlist)
 		g_slist_free_full (net->commandlist, (GDestroyNotify) servlist_command_free);
-	if (net->comment)
-		free (net->comment);
-	if (net->encoding)
-		free (net->encoding);
-	free (net->name);
-	free (net);
+	g_free (net->encoding);
+	g_free (net->name);
+	g_free (net);
 
 	/* for safety */
 	list = serv_list;
@@ -1110,10 +927,8 @@ servlist_net_add (char *name, char *comment, int prepend)
 {
 	ircnet *net;
 
-	net = malloc (sizeof (ircnet));
-	memset (net, 0, sizeof (ircnet));
-	net->name = strdup (name);
-/*	net->comment = strdup (comment);*/
+	net = g_new0 (ircnet, 1);
+	net->name = g_strdup (name);
 	net->flags = FLAG_CYCLE | FLAG_USE_GLOBAL | FLAG_USE_PROXY;
 
 	if (prepend)
@@ -1156,6 +971,10 @@ servlist_load_defaults (void)
 			{
 				servlist_command_add (net, def[i].connectcmd);
 			}
+			if (def[i].ssl)
+			{
+				net->flags |= FLAG_USE_SSL;
+			}
 
 			if (g_str_hash (def[i].network) == def_hash)
 			{
@@ -1210,25 +1029,25 @@ servlist_load (void)
 			switch (buf[0])
 			{
 			case 'I':
-				net->nick = strdup (buf + 2);
+				net->nick = g_strdup (buf + 2);
 				break;
 			case 'i':
-				net->nick2 = strdup (buf + 2);
+				net->nick2 = g_strdup (buf + 2);
 				break;
 			case 'U':
-				net->user = strdup (buf + 2);
+				net->user = g_strdup (buf + 2);
 				break;
 			case 'R':
-				net->real = strdup (buf + 2);
+				net->real = g_strdup (buf + 2);
 				break;
 			case 'P':
-				net->pass = strdup (buf + 2);
+				net->pass = g_strdup (buf + 2);
 				break;
 			case 'L':
 				net->logintype = atoi (buf + 2);
 				break;
 			case 'E':
-				net->encoding = strdup (buf + 2);
+				net->encoding = servlist_check_encoding (buf + 2) ? g_strdup (buf + 2) : g_strdup ("UTF-8");
 				break;
 			case 'F':
 				net->flags = atoi (buf + 2);
@@ -1258,7 +1077,7 @@ servlist_load (void)
 			case 'A':
 				if (!net->pass)
 				{
-					net->pass = strdup (buf + 2);
+					net->pass = g_strdup (buf + 2);
 					if (!net->logintype)
 					{
 						net->logintype = LOGIN_SASL;
@@ -1267,7 +1086,7 @@ servlist_load (void)
 			case 'B':
 				if (!net->pass)
 				{
-					net->pass = strdup (buf + 2);
+					net->pass = g_strdup (buf + 2);
 					if (!net->logintype)
 					{
 						net->logintype = LOGIN_NICKSERV;
@@ -1302,13 +1121,6 @@ servlist_check_encoding (char *charset)
 	if (c)
 		c[0] = 0;
 
-	if (!g_ascii_strcasecmp (charset, "IRC")) /* special case */
-	{
-		if (c)
-			c[0] = ' ';
-		return TRUE;
-	}
-
 	gic = g_iconv_open (charset, "UTF-8");
 
 	if (c)
@@ -1379,8 +1191,7 @@ servlist_save (void)
 			fprintf (fp, "P=%s\n", net->pass);
 		if (net->logintype)
 			fprintf (fp, "L=%d\n", net->logintype);
-		if (net->encoding && g_ascii_strcasecmp (net->encoding, "System") &&
-			 g_ascii_strcasecmp (net->encoding, "System default"))
+		if (net->encoding)
 		{
 			fprintf (fp, "E=%s\n", net->encoding);
 			if (!servlist_check_encoding (net->encoding))
diff --git a/src/common/servlist.h b/src/common/servlist.h
index 6d6f1bd3..a305aede 100644
--- a/src/common/servlist.h
+++ b/src/common/servlist.h
@@ -45,7 +45,6 @@ typedef struct ircnet
 	char *real;
 	char *pass;
 	int logintype;
-	char *comment;
 	char *encoding;
 	GSList *servlist;
 	GSList *commandlist;
diff --git a/src/common/ssl.c b/src/common/ssl.c
index cfa9b6cf..f4e23665 100644
--- a/src/common/ssl.c
+++ b/src/common/ssl.c
@@ -25,18 +25,29 @@
 #include "inet.h"				  /* make it first to avoid macro redefinitions */
 #include <openssl/ssl.h>		  /* SSL_() */
 #include <openssl/err.h>		  /* ERR_() */
+#include <openssl/x509v3.h>
 #ifdef WIN32
 #include <openssl/rand.h>		  /* RAND_seed() */
 #endif
-#include "../../config.h"
+#include "config.h"
 #include <time.h>				  /* asctime() */
 #include <string.h>				  /* strncpy() */
 #include "ssl.h"				  /* struct cert_info */
 
 #include <glib.h>
 #include <glib/gprintf.h>
+#include <gio/gio.h>
 #include "util.h"
 
+/* If openssl was built without ec */
+#ifndef SSL_OP_SINGLE_ECDH_USE
+#define SSL_OP_SINGLE_ECDH_USE 0
+#endif
+
+#ifndef SSL_OP_NO_COMPRESSION
+#define SSL_OP_NO_COMPRESSION 0
+#endif
+
 /* globals */
 static struct chiper_info chiper_info;		/* static buffer for _SSL_get_cipher_info() */
 static char err_buf[256];			/* generic error buffer */
@@ -69,32 +80,29 @@ __SSL_critical_error (char *funcname)
 /* +++++ SSL functions +++++ */
 
 SSL_CTX *
-_SSL_context_init (void (*info_cb_func), int server)
+_SSL_context_init (void (*info_cb_func))
 {
 	SSL_CTX *ctx;
-#ifdef WIN32
-	int i, r;
-#endif
 
 	SSLeay_add_ssl_algorithms ();
 	SSL_load_error_strings ();
-	ctx = SSL_CTX_new (server ? SSLv23_server_method() : SSLv23_client_method ());
+	ctx = SSL_CTX_new (SSLv23_client_method ());
 
 	SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_BOTH);
 	SSL_CTX_set_timeout (ctx, 300);
+	SSL_CTX_set_options (ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3
+							  |SSL_OP_NO_COMPRESSION
+							  |SSL_OP_SINGLE_DH_USE|SSL_OP_SINGLE_ECDH_USE
+							  |SSL_OP_NO_TICKET
+							  |SSL_OP_CIPHER_SERVER_PREFERENCE);
+
+#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined (OPENSSL_NO_COMP) /* workaround for OpenSSL 0.9.8 */
+	sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
+#endif
 
 	/* used in SSL_connect(), SSL_accept() */
 	SSL_CTX_set_info_callback (ctx, info_cb_func);
 
-#ifdef WIN32
-	/* under win32, OpenSSL needs to be seeded with some randomness */
-	for (i = 0; i < 128; i++)
-	{
-		r = rand ();
-		RAND_seed ((unsigned char *)&r, sizeof (r));
-	}
-#endif
-
 	return(ctx);
 }
 
@@ -329,3 +337,202 @@ _SSL_close (SSL * ssl)
 	SSL_free (ssl);
 	ERR_remove_state (0);		  /* free state buffer */
 }
+
+/* Hostname validation code based on OpenBSD's libtls. */
+
+static int
+_SSL_match_hostname (const char *cert_hostname, const char *hostname)
+{
+	const char *cert_domain, *domain, *next_dot;
+
+	if (g_ascii_strcasecmp (cert_hostname, hostname) == 0)
+		return 0;
+
+	/* Wildcard match? */
+	if (cert_hostname[0] == '*')
+	{
+		/*
+		 * Valid wildcards:
+		 * - "*.domain.tld"
+		 * - "*.sub.domain.tld"
+		 * - etc.
+		 * Reject "*.tld".
+		 * No attempt to prevent the use of eg. "*.co.uk".
+		 */
+		cert_domain = &cert_hostname[1];
+		/* Disallow "*"  */
+		if (cert_domain[0] == '\0')
+			return -1;
+		/* Disallow "*foo" */
+		if (cert_domain[0] != '.')
+			return -1;
+		/* Disallow "*.." */
+		if (cert_domain[1] == '.')
+			return -1;
+		next_dot = strchr (&cert_domain[1], '.');
+		/* Disallow "*.bar" */
+		if (next_dot == NULL)
+			return -1;
+		/* Disallow "*.bar.." */
+		if (next_dot[1] == '.')
+			return -1;
+
+		domain = strchr (hostname, '.');
+
+		/* No wildcard match against a hostname with no domain part. */
+		if (domain == NULL || strlen(domain) == 1)
+			return -1;
+
+		if (g_ascii_strcasecmp (cert_domain, domain) == 0)
+			return 0;
+	}
+
+	return -1;
+}
+
+static int
+_SSL_check_subject_altname (X509 *cert, const char *host)
+{
+	STACK_OF(GENERAL_NAME) *altname_stack = NULL;
+	GInetAddress *addr;
+	GSocketFamily family;
+	int type = GEN_DNS;
+	int count, i;
+	int rv = -1;
+
+	altname_stack = X509_get_ext_d2i (cert, NID_subject_alt_name, NULL, NULL);
+	if (altname_stack == NULL)
+		return -1;
+
+	addr = g_inet_address_new_from_string (host);
+	if (addr != NULL)
+	{
+		family = g_inet_address_get_family (addr);
+		if (family == G_SOCKET_FAMILY_IPV4 || family == G_SOCKET_FAMILY_IPV6)
+			type = GEN_IPADD;
+	}
+
+	count = sk_GENERAL_NAME_num(altname_stack);
+	for (i = 0; i < count; i++)
+	{
+		GENERAL_NAME *altname;
+
+		altname = sk_GENERAL_NAME_value (altname_stack, i);
+
+		if (altname->type != type)
+			continue;
+
+		if (type == GEN_DNS)
+		{
+			unsigned char *data;
+			int format;
+
+			format = ASN1_STRING_type (altname->d.dNSName);
+			if (format == V_ASN1_IA5STRING)
+			{
+				data = ASN1_STRING_data (altname->d.dNSName);
+
+				if (ASN1_STRING_length (altname->d.dNSName) != (int)strlen(data))
+				{
+					g_warning("NUL byte in subjectAltName, probably a malicious certificate.\n");
+					rv = -2;
+					break;
+				}
+
+				if (_SSL_match_hostname (data, host) == 0)
+				{
+					rv = 0;
+					break;
+				}
+			}
+			else
+				g_warning ("unhandled subjectAltName dNSName encoding (%d)\n", format);
+
+		}
+		else if (type == GEN_IPADD)
+		{
+			unsigned char *data;
+			const guint8 *addr_bytes;
+			int datalen, addr_len;
+
+			datalen = ASN1_STRING_length (altname->d.iPAddress);
+			data = ASN1_STRING_data (altname->d.iPAddress);
+
+			addr_bytes = g_inet_address_to_bytes (addr);
+			addr_len = (int)g_inet_address_get_native_size (addr);
+
+			if (datalen == addr_len && memcmp (data, addr_bytes, addr_len) == 0)
+			{
+				rv = 0;
+				break;
+			}
+		}
+	}
+
+	if (addr != NULL)
+		g_object_unref (addr);
+	sk_GENERAL_NAME_pop_free (altname_stack, GENERAL_NAME_free);
+	return rv;
+}
+
+static int
+_SSL_check_common_name (X509 *cert, const char *host)
+{
+	X509_NAME *name;
+	char *common_name = NULL;
+	int common_name_len;
+	int rv = -1;
+	GInetAddress *addr;
+
+	name = X509_get_subject_name (cert);
+	if (name == NULL)
+		return -1;
+
+	common_name_len = X509_NAME_get_text_by_NID (name, NID_commonName, NULL, 0);
+	if (common_name_len < 0)
+		return -1;
+
+	common_name = g_malloc0 (common_name_len + 1);
+
+	X509_NAME_get_text_by_NID (name, NID_commonName, common_name, common_name_len + 1);
+
+	/* NUL bytes in CN? */
+	if (common_name_len != (int)strlen(common_name))
+	{
+		g_warning ("NUL byte in Common Name field, probably a malicious certificate.\n");
+		rv = -2;
+		goto out;
+	}
+
+	if ((addr = g_inet_address_new_from_string (host)) != NULL)
+	{
+		/*
+		 * We don't want to attempt wildcard matching against IP
+		 * addresses, so perform a simple comparison here.
+		 */
+		if (g_strcmp0 (common_name, host) == 0)
+			rv = 0;
+		else
+			rv = -1;
+
+		g_object_unref (addr);
+	}
+	else if (_SSL_match_hostname (common_name, host) == 0)
+		rv = 0;
+
+out:
+	g_free(common_name);
+	return rv;
+}
+
+int
+_SSL_check_hostname (X509 *cert, const char *host)
+{
+	int rv;
+
+	rv = _SSL_check_subject_altname (cert, host);
+	if (rv == 0 || rv == -2)
+		return rv;
+
+	return _SSL_check_common_name (cert, host);
+}
diff --git a/src/common/ssl.h b/src/common/ssl.h
index 9c729855..e722f831 100644
--- a/src/common/ssl.h
+++ b/src/common/ssl.h
@@ -41,7 +41,7 @@ struct chiper_info {
     int chiper_bits;
 };
 
-SSL_CTX *_SSL_context_init (void (*info_cb_func), int server);
+SSL_CTX *_SSL_context_init (void (*info_cb_func));
 #define _SSL_context_free(a)	SSL_CTX_free(a);
 
 SSL *_SSL_socket (SSL_CTX *ctx, int sd);
@@ -52,7 +52,7 @@ char *_SSL_set_verify (SSL_CTX *ctx, void *(verify_callback), char *cacert);
     int SSL_get_fd(SSL *);
 */
 void _SSL_close (SSL * ssl);
-
+int _SSL_check_hostname(X509 *cert, const char *host);
 int _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl);
 struct chiper_info *_SSL_get_cipher_info (SSL * ssl);
 
diff --git a/src/common/text.c b/src/common/text.c
index 329ef37b..cd9ea26e 100644
--- a/src/common/text.c
+++ b/src/common/text.c
@@ -51,6 +51,9 @@
 #include <canberra.h>
 #endif
 
+const gchar* unicode_fallback_string = "\357\277\275"; /* The Unicode replacement character 0xFFFD */
+const gchar* arbitrary_encoding_fallback_string = "?";
+
 struct pevt_stage1
 {
 	int len;
@@ -83,7 +86,7 @@ scrollback_get_filename (session *sess)
 		buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "scrollback" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s.txt", get_xdir (), net, chan);
 	else
 		buf = NULL;
-	free (chan);
+	g_free (chan);
 
 	return buf;
 }
@@ -173,11 +176,11 @@ scrollback_shrink (session *sess)
 		p++;
 	}
 
-	fh = g_open (file, O_CREAT | O_TRUNC | O_APPEND | O_WRONLY, 0644);
+	fh = g_open (file, O_CREAT | O_TRUNC | O_APPEND | O_WRONLY | OFLAGS, 0644);
 	g_free (file);
 	if (fh == -1)
 	{
-		free (buf);
+		g_free (buf);
 		return;
 	}
 
@@ -200,14 +203,13 @@ scrollback_shrink (session *sess)
 	}
 
 	close (fh);
-	free (buf);
+	g_free (buf);
 }
 
 static void
-scrollback_save (session *sess, char *text)
+scrollback_save (session *sess, char *text, time_t stamp)
 {
 	char *buf;
-	time_t stamp;
 	int len;
 
 	if (sess->type == SESS_SERVER && prefs.hex_gui_tab_server == 1)
@@ -229,13 +231,14 @@ scrollback_save (session *sess, char *text)
 		if ((buf = scrollback_get_filename (sess)) == NULL)
 			return;
 
-		sess->scrollfd = g_open (buf, O_CREAT | O_APPEND | O_WRONLY, 0644);
+		sess->scrollfd = g_open (buf, O_CREAT | O_APPEND | O_WRONLY | OFLAGS, 0644);
 		g_free (buf);
 		if (sess->scrollfd == -1)
 			return;
 	}
 
-	stamp = time (0);
+	if (!stamp)
+		stamp = time(0);
 	if (sizeof (stamp) == 4)	/* gcc will optimize one of these out */
 		buf = g_strdup_printf ("T %d ", (int) stamp);
 	else
@@ -298,13 +301,6 @@ scrollback_load (session *sess)
 		{
 			char *buf_tmp;
 
-			/* If nothing but funny trailing matter e.g. 0x0d or 0x0d0a, toss it */
-			if (n_bytes >= 1 && buf[0] == 0x0d)
-			{
-				g_free (buf);
-				continue;
-			}
-
 			n_bytes--;
 			buf_tmp = buf;
 			buf = g_strndup (buf_tmp, n_bytes);
@@ -319,9 +315,9 @@ scrollback_load (session *sess)
 			if (buf[0] == 'T')
 			{
 				if (sizeof (time_t) == 4)
-					stamp = strtoul (buf + 2, NULL, 10);
+					stamp = g_ascii_strtoull (buf + 2, NULL, 10);
 				else
-					stamp = strtoull (buf + 2, NULL, 10); /* in case time_t is 64 bits */
+					stamp = g_ascii_strtoull (buf + 2, NULL, 10); /* in case time_t is 64 bits */
 				text = strchr (buf + 3, ' ');
 				if (text && text[1])
 				{
@@ -383,7 +379,7 @@ log_close (session *sess)
 	{
 		currenttime = time (NULL);
 		write (sess->logfd, obuf,
-			 snprintf (obuf, sizeof (obuf) - 1, _("**** ENDING LOGGING AT %s\n"),
+			 g_snprintf (obuf, sizeof (obuf) - 1, _("**** ENDING LOGGING AT %s\n"),
 						  ctime (&currenttime)));
 		close (sess->logfd);
 		sess->logfd = -1;
@@ -393,9 +389,7 @@ log_close (session *sess)
 static void
 mkdir_p (char *filename)
 {
-	char *dirname;
-	
-	dirname = g_path_get_dirname (filename);
+	char *dirname = g_path_get_dirname (filename);
 
 	g_mkdir_with_parents (dirname, 0700);
 
@@ -408,7 +402,7 @@ log_create_filename (char *channame)
 	char *tmp, *ret;
 	int mbl;
 
-	ret = tmp = strdup (channame);
+	ret = tmp = g_strdup (channame);
 	while (*tmp)
 	{
 		mbl = g_utf8_skip[((unsigned char *)tmp)[0]];
@@ -507,34 +501,6 @@ log_insert_vars (char *buf, int bufsize, char *fmt, char *c, char *n, char *s)
 	}
 }
 
-static int
-logmask_is_fullpath ()
-{
-	/* Check if final path/filename is absolute or relative.
-	 * If one uses log mask variables, such as "%c/...", %c will be empty upon
-	 * connecting since there's no channel name yet, so we have to make sure
-	 * we won't try to write to the FS root. On Windows we can be sure it's
-	 * full path if the 2nd character is a colon since Windows doesn't allow
-	 * colons in filenames.
-	 */
-#ifdef WIN32
-	/* Treat it as full path if it
-	 * - starts with '\' which denotes the root directory of the current drive letter
-	 * - starts with a drive letter and followed by ':'
-	 */
-	if (prefs.hex_irc_logmask[0] == '\\' || (((prefs.hex_irc_logmask[0] >= 'A' && prefs.hex_irc_logmask[0] <= 'Z') || (prefs.hex_irc_logmask[0] >= 'a' && prefs.hex_irc_logmask[0] <= 'z')) && prefs.hex_irc_logmask[1] == ':'))
-#else
-	if (prefs.hex_irc_logmask[0] == '/')
-#endif
-	{
-		return 1;
-	}
-	else
-	{
-		return 0;
-	}
-}
-
 static char *
 log_create_pathname (char *servname, char *channame, char *netname)
 {
@@ -544,7 +510,7 @@ log_create_pathname (char *servname, char *channame, char *netname)
 
 	if (!netname)
 	{
-		netname = strdup ("NETWORK");
+		netname = g_strdup ("NETWORK");
 	}
 	else
 	{
@@ -554,7 +520,7 @@ log_create_pathname (char *servname, char *channame, char *netname)
 	/* first, everything is in UTF-8 */
 	if (!rfc_casecmp (channame, servname))
 	{
-		channame = strdup ("server");
+		channame = g_strdup ("server");
 	}
 	else
 	{
@@ -562,27 +528,29 @@ log_create_pathname (char *servname, char *channame, char *netname)
 	}
 
 	log_insert_vars (fname, sizeof (fname), prefs.hex_irc_logmask, channame, netname, servname);
-	free (channame);
-	free (netname);
+	g_free (channame);
+	g_free (netname);
 
 	/* insert time/date */
 	now = time (NULL);
 	strftime_utf8 (fnametime, sizeof (fnametime), fname, now);
 
-	/* create final path/filename */
-	if (logmask_is_fullpath ())
+	/* If one uses log mask variables, such as "%c/...", %c will be empty upon
+	 * connecting since there's no channel name yet, so we have to make sure
+	 * we won't try to write to the FS root. */
+	if (g_path_is_absolute (prefs.hex_irc_logmask))
 	{
-		snprintf (fname, sizeof (fname), "%s", fnametime);
+		g_snprintf (fname, sizeof (fname), "%s", fnametime);
 	}
 	else	/* relative path */
 	{
-		snprintf (fname, sizeof (fname), "%s" G_DIR_SEPARATOR_S "logs" G_DIR_SEPARATOR_S "%s", get_xdir (), fnametime);
+		g_snprintf (fname, sizeof (fname), "%s" G_DIR_SEPARATOR_S "logs" G_DIR_SEPARATOR_S "%s", get_xdir (), fnametime);
 	}
 
 	/* create all the subdirectories */
 	mkdir_p (fname);
 
-	return g_strdup(fname);
+	return g_strdup (fname);
 }
 
 static int
@@ -597,18 +565,14 @@ log_open_file (char *servname, char *channame, char *netname)
 	if (!file)
 		return -1;
 
-#ifdef WIN32
-	fd = g_open (file, O_CREAT | O_APPEND | O_WRONLY, S_IREAD|S_IWRITE);
-#else
-	fd = g_open (file, O_CREAT | O_APPEND | O_WRONLY, 0644);
-#endif
+	fd = g_open (file, O_CREAT | O_APPEND | O_WRONLY | OFLAGS, 0644);
 	g_free (file);
 
 	if (fd == -1)
 		return -1;
 	currenttime = time (NULL);
 	write (fd, buf,
-			 snprintf (buf, sizeof (buf), _("**** BEGIN LOGGING AT %s\n"),
+			 g_snprintf (buf, sizeof (buf), _("**** BEGIN LOGGING AT %s\n"),
 						  ctime (&currenttime)));
 
 	return fd;
@@ -625,14 +589,15 @@ log_open (session *sess)
 
 	if (!log_error && sess->logfd == -1)
 	{
-		char *message;
+		char *filename = log_create_pathname (sess->server->servername, sess->channel, server_get_network (sess->server, FALSE));
+		char *message = g_strdup_printf (_("* Can't open log file(s) for writing. Check the\npermissions on %s"), filename);
 
-		message = g_strdup_printf (_("* Can't open log file(s) for writing. Check the\npermissions on %s"),
-			log_create_pathname (sess->server->servername, sess->channel, server_get_network (sess->server, FALSE)));
+		g_free (filename);
 
 		fe_message (message, FE_MSG_WAIT | FE_MSG_ERROR);
 
 		g_free (message);
+
 		log_error = TRUE;
 	}
 }
@@ -659,34 +624,29 @@ log_open_or_close (session *sess)
 int
 get_stamp_str (char *fmt, time_t tim, char **ret)
 {
-	char *loc = NULL;
 	char dest[128];
-	gsize len;
+	gsize len_locale;
+	gsize len_utf8;
 
-	/* strftime wants the format string in LOCALE! */
-	if (!prefs.utf8_locale)
-	{
-		const gchar *charset;
+	/* strftime requires the format string to be in locale encoding. */
+	fmt = g_locale_from_utf8 (fmt, -1, NULL, NULL, NULL);
 
-		g_get_charset (&charset);
-		loc = g_convert_with_fallback (fmt, -1, charset, "UTF-8", "?", 0, 0, 0);
-		if (loc)
-			fmt = loc;
-	}
+	len_locale = strftime_validated (dest, sizeof (dest), fmt, localtime (&tim));
 
-	len = strftime_validated (dest, sizeof (dest), fmt, localtime (&tim));
-	if (len)
+	g_free (fmt);
+
+	if (len_locale == 0)
 	{
-		if (prefs.utf8_locale)
-			*ret = g_strdup (dest);
-		else
-			*ret = g_locale_to_utf8 (dest, len, 0, &len, 0);
+		return 0;
 	}
 
-	if (loc)
-		g_free (loc);
+	*ret = g_locale_to_utf8 (dest, len_locale, NULL, &len_utf8, NULL);
+	if (*ret == NULL)
+	{
+		return 0;
+	}
 
-	return len;
+	return len_utf8;
 }
 
 static void
@@ -709,22 +669,32 @@ log_write (session *sess, char *text, time_t ts)
 	}
 
 	if (sess->logfd == -1)
+	{
 		log_open (sess);
+	}
 
 	/* change to a different log file? */
-	file = log_create_pathname (sess->server->servername, sess->channel,
-										 server_get_network (sess->server, FALSE));
+	file = log_create_pathname (sess->server->servername, sess->channel, server_get_network (sess->server, FALSE));
 	if (file)
 	{
 		if (g_access (file, F_OK) != 0)
 		{
-			close (sess->logfd);
-			sess->logfd = log_open_file (sess->server->servername, sess->channel,
-												  server_get_network (sess->server, FALSE));
+			if (sess->logfd != -1)
+			{
+				close (sess->logfd);
+			}
+
+			sess->logfd = log_open_file (sess->server->servername, sess->channel, server_get_network (sess->server, FALSE));
 		}
+
 		g_free (file);
 	}
 
+	if (sess->logfd == -1)
+	{
+		return;
+	}
+
 	if (prefs.hex_stamp_log)
 	{
 		if (!ts) ts = time(0);
@@ -735,6 +705,7 @@ log_write (session *sess, char *text, time_t ts)
 			g_free (stamp);
 		}
 	}
+
 	temp = strip_color (text, -1, STRIP_ALL);
 	len = strlen (temp);
 	write (sess->logfd, temp, len);
@@ -744,156 +715,104 @@ log_write (session *sess, char *text, time_t ts)
 	g_free (temp);
 }
 
-/* converts a CP1252/ISO-8859-1(5) hybrid to UTF-8                           */
-/* Features: 1. It never fails, all 00-FF chars are converted to valid UTF-8 */
-/*           2. Uses CP1252 in the range 80-9f because ISO doesn't have any- */
-/*              thing useful in this range and it helps us receive from mIRC */
-/*           3. The five undefined chars in CP1252 80-9f are replaced with   */
-/*              ISO-8859-15 control codes.                                   */
-/*           4. Handles 0xa4 as a Euro symbol ala ISO-8859-15.               */
-/*           5. Uses ISO-8859-1 (which matches CP1252) for everything else.  */
-/*           6. This routine measured 3x faster than g_convert :)            */
-
-static unsigned char *
-iso_8859_1_to_utf8 (unsigned char *text, int len, gsize *bytes_written)
+/**
+ * Converts a given string using the given iconv converter. This is similar to g_convert_with_fallback, except that it is tolerant of sequences in
+ * the original input that are invalid even in from_encoding. g_convert_with_fallback fails for such text, whereas this function replaces such a
+ * sequence with the fallback string.
+ *
+ * If len is -1, strlen(text) is used to calculate the length. Do not pass -1 if text is supposed to contain \0 bytes, such as if from_encoding is a
+ * multi-byte encoding like UTF-16.
+ */
+gchar *
+text_convert_invalid (const gchar* text, gssize len, GIConv converter, const gchar *fallback, gsize *len_out)
 {
-	unsigned int idx;
-	unsigned char *res, *output;
-	static const unsigned short lowtable[] = /* 74 byte table for 80-a4 */
-	{
-	/* compressed utf-8 table: if the first byte's 0x20 bit is set, it
-	   indicates a 2-byte utf-8 sequence, otherwise prepend a 0xe2. */
-		0x82ac, /* 80 Euro. CP1252 from here on... */
-		0xe281, /* 81 NA */
-		0x809a, /* 82 */
-		0xe692, /* 83 */
-		0x809e, /* 84 */
-		0x80a6, /* 85 */
-		0x80a0, /* 86 */
-		0x80a1, /* 87 */
-		0xeb86, /* 88 */
-		0x80b0, /* 89 */
-		0xe5a0, /* 8a */
-		0x80b9, /* 8b */
-		0xe592, /* 8c */
-		0xe28d, /* 8d NA */
-		0xe5bd, /* 8e */
-		0xe28f, /* 8f NA */
-		0xe290, /* 90 NA */
-		0x8098, /* 91 */
-		0x8099, /* 92 */
-		0x809c, /* 93 */
-		0x809d, /* 94 */
-		0x80a2, /* 95 */
-		0x8093, /* 96 */
-		0x8094, /* 97 */
-		0xeb9c, /* 98 */
-		0x84a2, /* 99 */
-		0xe5a1, /* 9a */
-		0x80ba, /* 9b */
-		0xe593, /* 9c */
-		0xe29d, /* 9d NA */
-		0xe5be, /* 9e */
-		0xe5b8, /* 9f */
-		0xe2a0, /* a0 */
-		0xe2a1, /* a1 */
-		0xe2a2, /* a2 */
-		0xe2a3, /* a3 */
-		0x82ac  /* a4 ISO-8859-15 Euro. */
-	};
+	gchar *result_part;
+	gsize result_part_len;
+	const gchar *end;
+	gsize invalid_start_pos;
+	GString *result;
+	const gchar *current_start;
 
 	if (len == -1)
+	{
 		len = strlen (text);
+	}
 
-	/* worst case scenario: every byte turns into 3 bytes */
-	res = output = g_malloc ((len * 3) + 1);
-	if (!output)
-		return NULL;
+	end = text + len;
 
-	while (len)
+	/* Find the first position of an invalid sequence. */
+	result_part = g_convert_with_iconv (text, len, converter, &invalid_start_pos, &result_part_len, NULL);
+	if (result_part != NULL)
 	{
-		if (G_LIKELY (*text < 0x80))
+		/* All text converted successfully on the first try. Return it. */
+
+		if (len_out != NULL)
 		{
-			*output = *text;	/* ascii maps directly */
+			*len_out = result_part_len;
 		}
-		else if (*text <= 0xa4)	/* 80-a4 use a lookup table */
+
+		return result_part;
+	}
+
+	/* One or more invalid sequences exist that need to be replaced with the fallback. */
+
+	result = g_string_sized_new (len);
+	current_start = text;
+
+	for (;;)
+	{
+		g_assert (current_start + invalid_start_pos < end);
+
+		/* Convert everything before the position of the invalid sequence. It should be successful. */
+		result_part = g_convert_with_iconv (current_start, invalid_start_pos, converter, &invalid_start_pos, &result_part_len, NULL);
+		g_assert (result_part != NULL);
+		g_string_append_len (result, result_part, result_part_len);
+		g_free (result_part);
+
+		/* Append the fallback */
+		g_string_append (result, fallback);
+
+		/* Now try converting everything after the invalid sequence. */
+		current_start += invalid_start_pos + 1;
+
+		result_part = g_convert_with_iconv (current_start, end - current_start, converter, &invalid_start_pos, &result_part_len, NULL);
+		if (result_part != NULL)
 		{
-			idx = *text - 0x80;
-			if (lowtable[idx] & 0x2000)
-			{
-				*output++ = (lowtable[idx] >> 8) & 0xdf; /* 2 byte utf-8 */
-				*output = lowtable[idx] & 0xff;
-			}
-			else
+			/* The rest of the text converted successfully. Append it and return the whole converted text. */
+
+			g_string_append_len (result, result_part, result_part_len);
+			g_free (result_part);
+
+			if (len_out != NULL)
 			{
-				*output++ = 0xe2;	/* 3 byte utf-8 */
-				*output++ = (lowtable[idx] >> 8) & 0xff;
-				*output = lowtable[idx] & 0xff;
+				*len_out = result->len;
 			}
+
+			return g_string_free (result, FALSE);
 		}
-		else if (*text < 0xc0)
-		{
-			*output++ = 0xc2;
-			*output = *text;
-		}
-		else
-		{
-			*output++ = 0xc3;
-			*output = *text - 0x40;
-		}
-		output++;
-		text++;
-		len--;
-	}
-	*output = 0;	/* terminate */
-	*bytes_written = output - res;
 
-	return res;
+		/* The rest of the text didn't convert successfully. invalid_start_pos has the position of the next invalid sequence. */
+	}
 }
 
-char *
-text_validate (char **text, int *len)
+/**
+ * Replaces any invalid UTF-8 in the given text with the unicode replacement character.
+ */
+gchar *
+text_fixup_invalid_utf8 (const gchar* text, gssize len, gsize *len_out)
 {
-	char *utf;
-	gsize utf_len;
-
-	/* valid utf8? */
-	if (g_utf8_validate (*text, *len, 0))
-		return NULL;
-
-#ifdef WIN32
-	if (GetACP () == 1252) /* our routine is better than iconv's 1252 */
-#else
-	if (prefs.utf8_locale)
-#endif
-		/* fallback to iso-8859-1 */
-		utf = iso_8859_1_to_utf8 (*text, *len, &utf_len);
-	else
+	static GIConv utf8_fixup_converter = NULL;
+	if (utf8_fixup_converter == NULL)
 	{
-		/* fallback to locale */
-		utf = g_locale_to_utf8 (*text, *len, 0, &utf_len, NULL);
-		if (!utf)
-			utf = iso_8859_1_to_utf8 (*text, *len, &utf_len);
+		utf8_fixup_converter = g_iconv_open ("UTF-8", "UTF-8");
 	}
 
-	if (!utf) 
-	{
-		*text = g_strdup ("%INVALID%");
-		*len = 9;
-	} else
-	{
-		*text = utf;
-		*len = utf_len;
-	}
-
-	return utf;
+	return text_convert_invalid (text, len, utf8_fixup_converter, unicode_fallback_string, len_out);
 }
 
 void
 PrintTextTimeStamp (session *sess, char *text, time_t timestamp)
 {
-	char *conv;
-
 	if (!sess)
 	{
 		if (!sess_list)
@@ -902,22 +821,19 @@ PrintTextTimeStamp (session *sess, char *text, time_t timestamp)
 	}
 
 	/* make sure it's valid utf8 */
-	if (text[0] == 0)
+	if (text[0] == '\0')
 	{
-		text = "\n";
-		conv = NULL;
-	} else
+		text = g_strdup ("\n");
+	}
+	else
 	{
-		int len = -1;
-		conv = text_validate ((char **)&text, &len);
+		text = text_fixup_invalid_utf8 (text, -1, NULL);
 	}
 
 	log_write (sess, text, timestamp);
-	scrollback_save (sess, text);
+	scrollback_save (sess, text, timestamp);
 	fe_print_text (sess, text, timestamp, FALSE);
-
-	if (conv)
-		g_free (conv);
+	g_free (text);
 }
 
 void
@@ -1004,7 +920,7 @@ PrintTextTimeStampf (session *sess, time_t timestamp, const char *format, ...)
    Each XP_TE_* signal is hard coded to call text_emit which calls
    display_event which decodes the data
 
-   This means that this system *should be faster* than snprintf because
+   This means that this system *should be faster* than g_snprintf because
    it always 'knows' that format of the string (basically is preparses much
    of the work)
 
@@ -1211,26 +1127,26 @@ static char * const pevt_chanrmlimit_help[] = {
 };
 
 static char * const pevt_chandeop_help[] = {
-	N_("The nick of the person of did the deop'ing"),
+	N_("The nick of the person who did the deop'ing"),
 	N_("The nick of the person who has been deop'ed"),
 };
 static char * const pevt_chandehop_help[] = {
-	N_("The nick of the person of did the dehalfop'ing"),
+	N_("The nick of the person who did the dehalfop'ing"),
 	N_("The nick of the person who has been dehalfop'ed"),
 };
 
 static char * const pevt_chandevoice_help[] = {
-	N_("The nick of the person of did the devoice'ing"),
+	N_("The nick of the person who did the devoice'ing"),
 	N_("The nick of the person who has been devoice'ed"),
 };
 
 static char * const pevt_chanunban_help[] = {
-	N_("The nick of the person of did the unban'ing"),
+	N_("The nick of the person who did the unban'ing"),
 	N_("The ban mask"),
 };
 
 static char * const pevt_chanunquiet_help[] = {
-	N_("The nick of the person of did the unquiet'ing"),
+	N_("The nick of the person who did the unquiet'ing"),
 	N_("The quiet mask"),
 };
 
@@ -1569,14 +1485,13 @@ pevent_load_defaults ()
 
 	for (i = 0; i < NUM_XP; i++)
 	{
-		if (pntevts_text[i])
-			free (pntevts_text[i]);
+		g_free (pntevts_text[i]);
 
 		/* make-te.c sets this 128 flag (DON'T call gettext() flag) */
 		if (te[i].num_args & 128)
-			pntevts_text[i] = strdup (te[i].def);
+			pntevts_text[i] = g_strdup (te[i].def);
 		else
-			pntevts_text[i] = strdup (_(te[i].def));
+			pntevts_text[i] = g_strdup (_(te[i].def));
 	}
 }
 
@@ -1588,19 +1503,18 @@ pevent_make_pntevts ()
 
 	for (i = 0; i < NUM_XP; i++)
 	{
-		if (pntevts[i] != NULL)
-			free (pntevts[i]);
+		g_free (pntevts[i]);
 		if (pevt_build_string (pntevts_text[i], &(pntevts[i]), &m) != 0)
 		{
-			snprintf (out, sizeof (out),
+			g_snprintf (out, sizeof (out),
 						 _("Error parsing event %s.\nLoading default."), te[i].name);
 			fe_message (out, FE_MSG_WARN);
-			free (pntevts_text[i]);
+			g_free (pntevts_text[i]);
 			/* make-te.c sets this 128 flag (DON'T call gettext() flag) */
 			if (te[i].num_args & 128)
-				pntevts_text[i] = strdup (te[i].def);
+				pntevts_text[i] = g_strdup (te[i].def);
 			else
-				pntevts_text[i] = strdup (_(te[i].def));
+				pntevts_text[i] = g_strdup (_(te[i].def));
 			if (pevt_build_string (pntevts_text[i], &(pntevts[i]), &m) != 0)
 			{
 				fprintf (stderr,
@@ -1622,22 +1536,17 @@ pevent_make_pntevts ()
 static void
 pevent_trigger_load (int *i_penum, char **i_text, char **i_snd)
 {
-	int penum = *i_penum, len;
+	int penum = *i_penum;
 	char *text = *i_text, *snd = *i_snd;
 
 	if (penum != -1 && text != NULL)
 	{
-		len = strlen (text) + 1;
-		if (pntevts_text[penum])
-			free (pntevts_text[penum]);
-		pntevts_text[penum] = malloc (len);
-		memcpy (pntevts_text[penum], text, len);
+		g_free (pntevts_text[penum]);
+		pntevts_text[penum] = g_strdup (text);
 	}
 
-	if (text)
-		free (text);
-	if (snd)
-		free (snd);
+	g_free (text);
+	g_free (snd);
 	*i_text = NULL;
 	*i_snd = NULL;
 	*i_penum = 0;
@@ -1690,7 +1599,7 @@ pevent_load (char *filename)
 		close (fd);
 		return 1;
 	}
-	ibuf = malloc (st.st_size);
+	ibuf = g_malloc (st.st_size);
 	read (fd, ibuf, st.st_size);
 	close (fd);
 
@@ -1706,8 +1615,6 @@ pevent_load (char *filename)
 			continue;
 		*ofs = 0;
 		ofs++;
-		/*if (*ofs == 0)
-			continue;*/
 
 		if (strcmp (buf, "event_name") == 0)
 		{
@@ -1717,53 +1624,16 @@ pevent_load (char *filename)
 			continue;
 		} else if (strcmp (buf, "event_text") == 0)
 		{
-			if (text)
-				free (text);
-
-#if 0
-			/* This allows updating of old strings. We don't use new defaults
-				if the user has customized the strings (.e.g a text theme).
-				Hash of the old default is enough to identify and replace it.
-				This only works in English. */
-
-			switch (g_str_hash (ofs))
-			{
-			case 0x526743a4:
-		/* %C08,02 Hostmask                  PRIV NOTI CHAN CTCP INVI UNIG %O */
-				text = strdup (te[XP_TE_IGNOREHEADER].def);
-				break;
-
-			case 0xe91bc9c2:
-		/* %C08,02                                                         %O */
-				text = strdup (te[XP_TE_IGNOREFOOTER].def);
-				break;
-
-			case 0x1fbfdf22:
-		/* -%C10-%C11-%O$tDCC RECV: Cannot open $1 for writing - aborting. */
-				text = strdup (te[XP_TE_DCCFILEERR].def);
-				break;
-
-			default:
-				text = strdup (ofs);
-			}
-#else
-			text = strdup (ofs);
-#endif
-
-			continue;
-		}/* else if (strcmp (buf, "event_sound") == 0)
-		{
-			if (snd)
-				free (snd);
-			snd = strdup (ofs);
+			g_free (text);
+			text = g_strdup (ofs);
 			continue;
-		}*/
+		}
 
 		continue;
 	}
 
 	pevent_trigger_load (&penum, &text, &snd);
-	free (ibuf);
+	g_free (ibuf);
 	return 0;
 }
 
@@ -1777,13 +1647,13 @@ pevent_check_all_loaded ()
 		if (pntevts_text[i] == NULL)
 		{
 			/*printf ("%s\n", te[i].name);
-			snprintf(out, sizeof(out), "The data for event %s failed to load. Reverting to defaults.\nThis may be because a new version of HexChat is loading an old config file.\n\nCheck all print event texts are correct", evtnames[i]);
+			g_snprintf(out, sizeof(out), "The data for event %s failed to load. Reverting to defaults.\nThis may be because a new version of HexChat is loading an old config file.\n\nCheck all print event texts are correct", evtnames[i]);
 			   gtkutil_simpledialog(out); */
 			/* make-te.c sets this 128 flag (DON'T call gettext() flag) */
 			if (te[i].num_args & 128)
-				pntevts_text[i] = strdup (te[i].def);
+				pntevts_text[i] = g_strdup (te[i].def);
 			else
-				pntevts_text[i] = strdup (_(te[i].def));
+				pntevts_text[i] = g_strdup (_(te[i].def));
 		}
 	}
 }
@@ -1808,9 +1678,10 @@ load_text_events ()
 #define ARG_FLAG(argn) (1 << (argn))
 
 void
-format_event (session *sess, int index, char **args, char *o, int sizeofo, unsigned int stripcolor_args)
+format_event (session *sess, int index, char **args, char *o, gsize sizeofo, unsigned int stripcolor_args)
 {
-	int len, oi, ii, numargs;
+	int len, ii, numargs;
+	gsize oi;
 	char *i, *ar, d, a, done_all = FALSE;
 
 	i = pntevts[index];
@@ -1868,19 +1739,10 @@ format_event (session *sess, int index, char **args, char *o, int sizeofo, unsig
 			done_all = TRUE;
 			continue;
 		case 3:
-/*			if (sess->type == SESS_DIALOG)
-			{
-				if (prefs.dialog_indent_nicks)
-					o[oi++] = '\t';
-				else
-					o[oi++] = ' ';
-			} else
-			{*/
-				if (prefs.hex_text_indent)
-					o[oi++] = '\t';
-				else
-					o[oi++] = ' ';
-			/*}*/
+			if (prefs.hex_text_indent)
+				o[oi++] = '\t';
+			else
+				o[oi++] = ' ';
 			break;
 		}
 	}
@@ -1908,7 +1770,7 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 	int oi, ii, max = -1, len, x;
 
 	len = strlen (input);
-	i = malloc (len + 1);
+	i = g_malloc (len + 1);
 	memcpy (i, input, len + 1);
 	check_special_chars (i, TRUE);
 
@@ -1933,14 +1795,14 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 		}
 		if (oi > 0)
 		{
-			s = (struct pevt_stage1 *) malloc (sizeof (struct pevt_stage1));
+			s = g_new (struct pevt_stage1, 1);
 			if (base == NULL)
 				base = s;
 			if (last != NULL)
 				last->next = s;
 			last = s;
 			s->next = NULL;
-			s->data = malloc (oi + sizeof (int) + 1);
+			s->data = g_malloc (oi + sizeof (int) + 1);
 			s->len = oi + sizeof (int) + 1;
 			clen += oi + sizeof (int) + 1;
 			s->data[0] = 0;
@@ -1951,12 +1813,12 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 		if (ii == len)
 		{
 			fe_message ("String ends with a $", FE_MSG_WARN);
-			return 1;
+			goto err;
 		}
 		d = i[ii++];
 		if (d == 'a')
-		{								  /* Hex value */
-			x = 0;
+		{
+			/* Hex value */
 			if (ii == len)
 				goto a_len_error;
 			d = i[ii++];
@@ -1977,24 +1839,24 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 			o[oi++] = x;
 			continue;
 
-		 a_len_error:
+		a_len_error:
 			fe_message ("String ends in $a", FE_MSG_WARN);
-			return 1;
-		 a_range_error:
+			goto err;
+		a_range_error:
 			fe_message ("$a value is greater than 255", FE_MSG_WARN);
-			return 1;
+			goto err;
 		}
 		if (d == 't')
 		{
 			/* Tab - if tabnicks is set then write '\t' else ' ' */
-			s = (struct pevt_stage1 *) malloc (sizeof (struct pevt_stage1));
+			s = g_new (struct pevt_stage1, 1);
 			if (base == NULL)
 				base = s;
 			if (last != NULL)
 				last->next = s;
 			last = s;
 			s->next = NULL;
-			s->data = malloc (1);
+			s->data = g_malloc (1);
 			s->len = 1;
 			clen += 1;
 			s->data[0] = 3;
@@ -2003,21 +1865,21 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 		}
 		if (d < '1' || d > '9')
 		{
-			snprintf (o, sizeof (o), "Error, invalid argument $%c\n", d);
+			g_snprintf (o, sizeof (o), "Error, invalid argument $%c\n", d);
 			fe_message (o, FE_MSG_WARN);
-			return 1;
+			goto err;
 		}
 		d -= '0';
 		if (max < d)
 			max = d;
-		s = (struct pevt_stage1 *) malloc (sizeof (struct pevt_stage1));
+		s = g_new (struct pevt_stage1, 1);
 		if (base == NULL)
 			base = s;
 		if (last != NULL)
 			last->next = s;
 		last = s;
 		s->next = NULL;
-		s->data = malloc (2);
+		s->data = g_malloc (2);
 		s->len = 2;
 		clen += 2;
 		s->data[0] = 1;
@@ -2025,14 +1887,14 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 	}
 	if (oi > 0)
 	{
-		s = (struct pevt_stage1 *) malloc (sizeof (struct pevt_stage1));
+		s = g_new (struct pevt_stage1, 1);
 		if (base == NULL)
 			base = s;
 		if (last != NULL)
 			last->next = s;
 		last = s;
 		s->next = NULL;
-		s->data = malloc (oi + sizeof (int) + 1);
+		s->data = g_malloc (oi + sizeof (int) + 1);
 		s->len = oi + sizeof (int) + 1;
 		clen += oi + sizeof (int) + 1;
 		s->data[0] = 0;
@@ -2040,39 +1902,54 @@ pevt_build_string (const char *input, char **output, int *max_arg)
 		memcpy (&(s->data[1 + sizeof (int)]), o, oi);
 		oi = 0;
 	}
-	s = (struct pevt_stage1 *) malloc (sizeof (struct pevt_stage1));
+	s = g_new (struct pevt_stage1, 1);
 	if (base == NULL)
 		base = s;
 	if (last != NULL)
 		last->next = s;
-	last = s;
 	s->next = NULL;
-	s->data = malloc (1);
+	s->data = g_malloc (1);
 	s->len = 1;
 	clen += 1;
 	s->data[0] = 2;
 
 	oi = 0;
 	s = base;
-	obuf = malloc (clen);
+	obuf = g_malloc (clen);
+
 	while (s)
 	{
 		next = s->next;
 		memcpy (&obuf[oi], s->data, s->len);
 		oi += s->len;
-		free (s->data);
-		free (s);
+		g_free (s->data);
+		g_free (s);
 		s = next;
 	}
 
-	free (i);
+	g_free (i);
 
 	if (max_arg)
 		*max_arg = max;
 	if (output)
 		*output = obuf;
+	else
+		g_free (obuf);
 
 	return 0;
+
+err:
+	while (s)
+	{
+		next = s->next;
+		g_free (s->data);
+		g_free (s);
+		s = next;
+	}
+
+	g_free(i);
+
+	return 1;
 }
 
 
@@ -2107,7 +1984,7 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d,
 
 	if (prefs.hex_text_color_nicks && (index == XP_TE_CHANACTION || index == XP_TE_CHANMSG))
 	{
-		snprintf (tbuf, sizeof (tbuf), "\003%d%s", text_color_of (a), a);
+		g_snprintf (tbuf, sizeof (tbuf), "\003%d%s", text_color_of (a), a);
 		a = tbuf;
 		stripcolor_args &= ~ARG_FLAG(1);	/* don't strip color from this argument */
 	}
@@ -2239,9 +2116,9 @@ pevent_save (char *fn)
 
 	for (i = 0; i < NUM_XP; i++)
 	{
-		write (fd, buf, snprintf (buf, sizeof (buf),
+		write (fd, buf, g_snprintf (buf, sizeof (buf),
 										  "event_name=%s\n", te[i].name));
-		write (fd, buf, snprintf (buf, sizeof (buf),
+		write (fd, buf, g_snprintf (buf, sizeof (buf),
 										  "event_text=%s\n\n", pntevts_text[i]));
 	}
 
@@ -2257,7 +2134,7 @@ char *sound_files[NUM_XP];
 void
 sound_beep (session *sess)
 {
-	if (!prefs.hex_gui_focus_omitalerts || !fe_gui_info (sess, 0) == 1)
+	if (!prefs.hex_gui_focus_omitalerts || fe_gui_info (sess, 0) != 1)
 	{
 		if (sound_files[XP_TE_BEEP] && sound_files[XP_TE_BEEP][0])
 			/* user defined beep _file_ */
@@ -2283,12 +2160,8 @@ sound_play (const char *file, gboolean quiet)
 		return;
 	}
 
-#ifdef WIN32
 	/* check for fullpath */
-	if (file[0] == '\\' || (((file[0] >= 'A' && file[0] <= 'Z') || (file[0] >= 'a' && file[0] <= 'z')) && file[1] == ':'))
-#else
-	if (file[0] == '/')
-#endif
+	if (g_path_is_absolute (file))
 	{
 		wavfile = g_strdup (file);
 	}
@@ -2363,9 +2236,8 @@ sound_load_event (char *evt, char *file)
 
 	if (file[0] && pevent_find (evt, &i) != -1)
 	{
-		if (sound_files[i])
-			free (sound_files[i]);
-		sound_files[i] = strdup (file);
+		g_free (sound_files[i]);
+		sound_files[i] = g_strdup (file);
 	}
 }
 
@@ -2417,9 +2289,9 @@ sound_save ()
 	{
 		if (sound_files[i] && sound_files[i][0])
 		{
-			write (fd, buf, snprintf (buf, sizeof (buf),
+			write (fd, buf, g_snprintf (buf, sizeof (buf),
 											  "event=%s\n", te[i].name));
-			write (fd, buf, snprintf (buf, sizeof (buf),
+			write (fd, buf, g_snprintf (buf, sizeof (buf),
 											  "sound=%s\n\n", sound_files[i]));
 		}
 	}
diff --git a/src/common/text.h b/src/common/text.h
index 9a385167..28fc0c0d 100644
--- a/src/common/text.h
+++ b/src/common/text.h
@@ -57,11 +57,15 @@ void text_emit (int index, session *sess, char *a, char *b, char *c, char *d,
 		time_t timestamp);
 int text_emit_by_name (char *name, session *sess, time_t timestamp,
 					   char *a, char *b, char *c, char *d);
-char *text_validate (char **text, int *len);
+gchar *text_convert_invalid (const gchar* text, gssize len, GIConv converter, const gchar *fallback, gsize *len_out);
+gchar *text_fixup_invalid_utf8 (const gchar* text, gssize len, gsize *len_out);
 int get_stamp_str (char *fmt, time_t tim, char **ret);
-void format_event (session *sess, int index, char **args, char *o, int sizeofo, unsigned int stripcolor_args);
+void format_event (session *sess, int index, char **args, char *o, gsize sizeofo, unsigned int stripcolor_args);
 char *text_find_format_string (char *name);
- 
+
+extern const gchar* unicode_fallback_string;
+extern const gchar* arbitrary_encoding_fallback_string;
+
 void sound_play (const char *file, gboolean quiet);
 void sound_play_event (int i);
 void sound_beep (session *);
diff --git a/src/common/tree.c b/src/common/tree.c
index 587d15f0..b9a894d2 100644
--- a/src/common/tree.c
+++ b/src/common/tree.c
@@ -42,7 +42,7 @@ struct _tree
 tree *
 tree_new (tree_cmp_func *cmp, void *data)
 {
-	tree *t = calloc (1, sizeof (tree));
+	tree *t = g_new0 (tree, 1);
 	t->cmp = cmp;
 	t->data = data;
 	return t;
@@ -53,9 +53,8 @@ tree_destroy (tree *t)
 {
 	if (t)
 	{
-		if (t->array)
-			free (t->array);
-		free (t);
+		g_free (t->array);
+		g_free (t);
 	}
 }
 
diff --git a/src/common/tree.h b/src/common/tree.h
index 848f5abf..8cde93ea 100644
--- a/src/common/tree.h
+++ b/src/common/tree.h
@@ -20,6 +20,8 @@
 #ifndef HEXCHAT_TREE_H
 #define HEXCHAT_TREE_H
 
+#include <glib.h>
+
 typedef struct _tree tree;
 
 typedef int (tree_cmp_func) (const void *keya, const void *keyb, void *data);
diff --git a/src/common/url.c b/src/common/url.c
index 1321374f..0354d98c 100644
--- a/src/common/url.c
+++ b/src/common/url.c
@@ -53,7 +53,7 @@ static gboolean match_path (const char *word, int *start, int *end);
 static int
 url_free (char *url, void *data)
 {
-	free (url);
+	g_free (url);
 	return TRUE;
 }
 
@@ -124,13 +124,7 @@ url_add (char *urltext, int len)
 		return;
 	}
 
-	data = malloc (len + 1);
-	if (!data)
-	{
-		return;
-	}
-	memcpy (data, urltext, len);
-	data[len] = 0;
+	data = g_strndup (urltext, len);
 
 	if (data[len - 1] == '.')	/* chop trailing dot */
 	{
@@ -151,7 +145,7 @@ url_add (char *urltext, int len)
 	/* the URL is saved already, only continue if we need the URL grabber too */
 	if (!prefs.hex_url_grabber)
 	{
-		free (data);
+		g_free (data);
 		return;
 	}
 
@@ -163,7 +157,7 @@ url_add (char *urltext, int len)
 
 	if (url_find (data))
 	{
-		free (data);
+		g_free (data);
 		return;
 	}
 
@@ -180,7 +174,7 @@ url_add (char *urltext, int len)
 
 			pos = tree_remove_at_pos (url_tree, 0);
 			g_tree_remove (url_btree, pos);
-			free (pos);
+			g_free (pos);
 		}
 	}
 
@@ -332,7 +326,7 @@ static char *commands[] = {
 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
 
 void
-url_check_line (char *buf, int len)
+url_check_line (char *buf)
 {
 	GRegex *re(void);
 	GMatchInfo *gmi;
@@ -415,7 +409,7 @@ regex_match (const GRegex *re, const char *word, int *start, int *end)
 }
 
 /*	Miscellaneous description --- */
-#define DOMAIN "[_\\pL\\pN][-_\\pL\\pN]*(\\.[-_\\pL\\pN]+)*"
+#define DOMAIN "[_\\pL\\pN\\pS][-_\\pL\\pN\\pS]*(\\.[-_\\pL\\pN\\pS]+)*"
 #define TLD "\\.[\\pL][-\\pL\\pN]*[\\pL]"
 #define IPADDR "[0-9]{1,3}(\\.[0-9]{1,3}){3}"
 #define IPV6GROUP "([0-9a-f]{0,4})"
@@ -429,7 +423,7 @@ regex_match (const GRegex *re, const char *word, int *start, int *end)
 #define OPT_PORT "(" PORT ")?"
 
 static GRegex *
-make_re (char *grist)
+make_re (const char *grist)
 {
 	GRegex *ret;
 	GError *err = NULL;
@@ -587,18 +581,14 @@ re_url (void)
 		
 		if (uri[i].flags & URI_PATH)
 		{
-			char *sep_escaped;
-			
-			sep_escaped = g_regex_escape_string (uri[i].path_sep, 
-							     strlen(uri[i].path_sep));
+			char *sep_escaped = g_regex_escape_string (uri[i].path_sep, strlen(uri[i].path_sep));
 
-			g_string_append_printf(grist_gstr, "(" "%s" PATH ")?",
-					       sep_escaped);
+			g_string_append_printf (grist_gstr, "(" "%s" PATH ")?", sep_escaped);
 
-			g_free(sep_escaped);
+			g_free (sep_escaped);
 		}
 
-		g_string_append(grist_gstr, ")");
+		g_string_append (grist_gstr, ")");
 	}
 
 	grist = g_string_free (grist_gstr, FALSE);
diff --git a/src/common/url.h b/src/common/url.h
index 676f9a6d..1b1deb3d 100644
--- a/src/common/url.h
+++ b/src/common/url.h
@@ -36,6 +36,6 @@ void url_clear (void);
 void url_save_tree (const char *fname, const char *mode, gboolean fullpath);
 int url_last (int *, int *);
 int url_check_word (const char *word);
-void url_check_line (char *buf, int len);
+void url_check_line (char *buf);
 
 #endif
diff --git a/src/common/userlist.c b/src/common/userlist.c
index e08cb857..54ed6f03 100644
--- a/src/common/userlist.c
+++ b/src/common/userlist.c
@@ -29,7 +29,7 @@
 #include "util.h"
 
 
-static int
+int
 nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2)
 {
 	unsigned int access1 = user1->access;
@@ -52,30 +52,12 @@ nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2)
 	return serv->p_cmp (user1->nick, user2->nick);
 }
 
-static int
+int
 nick_cmp_alpha (struct User *user1, struct User *user2, server *serv)
 {
 	return serv->p_cmp (user1->nick, user2->nick);
 }
 
-static int
-nick_cmp (struct User *user1, struct User *user2, server *serv)
-{
-	switch (prefs.hex_gui_ulist_sort)
-	{
-	case 0:
-		return nick_cmp_az_ops (serv, user1, user2);
-	case 1:
-		return serv->p_cmp (user1->nick, user2->nick);
-	case 2:
-		return -1 * nick_cmp_az_ops (serv, user1, user2);
-	case 3:
-		return -1 * serv->p_cmp (user1->nick, user2->nick);
-	default:
-		return -1;
-	}
-}
-
 /*
  insert name in appropriate place in linked list. Returns row number or:
   -1: duplicate
@@ -86,11 +68,9 @@ userlist_insertname (session *sess, struct User *newuser)
 {
 	if (!sess->usertree)
 	{
-		sess->usertree = tree_new ((tree_cmp_func *)nick_cmp, sess->server);
-		sess->usertree_alpha = tree_new ((tree_cmp_func *)nick_cmp_alpha, sess->server);
+		sess->usertree = tree_new ((tree_cmp_func *)nick_cmp_alpha, sess->server);
 	}
 
-	tree_insert (sess->usertree_alpha, newuser);
 	return tree_insert (sess->usertree, newuser);
 }
 
@@ -121,13 +101,12 @@ userlist_set_account (struct session *sess, char *nick, char *account)
 	user = userlist_find (sess, nick);
 	if (user)
 	{
-		if (user->account)
-			free (user->account);
+		g_free (user->account);
 			
 		if (strcmp (account, "*") == 0)
 			user->account = NULL;
 		else
-			user->account = strdup (account);
+			user->account = g_strdup (account);
 			
 		/* gui doesnt currently reflect login status, maybe later
 		fe_userlist_rehash (sess, user); */
@@ -148,14 +127,14 @@ userlist_add_hostname (struct session *sess, char *nick, char *hostname,
 		{
 			if (prefs.hex_gui_ulist_show_hosts)
 				do_rehash = TRUE;
-			user->hostname = strdup (hostname);
+			user->hostname = g_strdup (hostname);
 		}
 		if (!user->realname && realname && *realname)
-			user->realname = strdup (realname);
+			user->realname = g_strdup (realname);
 		if (!user->servername && servername)
-			user->servername = strdup (servername);
+			user->servername = g_strdup (servername);
 		if (!user->account && account && strcmp (account, "0") != 0)
-			user->account = strdup (account);
+			user->account = g_strdup (account);
 		if (away != 0xff)
 		{
 			if (user->away != away)
@@ -175,15 +154,11 @@ userlist_add_hostname (struct session *sess, char *nick, char *hostname,
 static int
 free_user (struct User *user, gpointer data)
 {
-	if (user->realname)
-		free (user->realname);
-	if (user->hostname)
-		free (user->hostname);
-	if (user->servername)
-		free (user->servername);
-	if (user->account)
-		free (user->account);
-	free (user);
+	g_free (user->realname);
+	g_free (user->hostname);
+	g_free (user->servername);
+	g_free (user->account);
+	g_free (user);
 
 	return TRUE;
 }
@@ -193,10 +168,8 @@ userlist_free (session *sess)
 {
 	tree_foreach (sess->usertree, (tree_traverse_func *)free_user, NULL);
 	tree_destroy (sess->usertree);
-	tree_destroy (sess->usertree_alpha);
 
 	sess->usertree = NULL;
-	sess->usertree_alpha = NULL;
 	sess->me = NULL;
 
 	sess->ops = 0;
@@ -224,8 +197,8 @@ userlist_find (struct session *sess, const char *name)
 {
 	int pos;
 
-	if (sess->usertree_alpha)
-		return tree_find (sess->usertree_alpha, name,
+	if (sess->usertree)
+		return tree_find (sess->usertree, name,
 								(tree_cmp_func *)find_cmp, sess->server, &pos);
 
 	return NULL;
@@ -248,7 +221,7 @@ userlist_find_global (struct server *serv, char *name)
 		}
 		list = list->next;
 	}
-	return 0;
+	return NULL;
 }
 
 static void
@@ -288,7 +261,7 @@ userlist_update_mode (session *sess, char *name, char mode, char sign)
 
 	/* remove from binary trees, before we loose track of it */
 	tree_remove (sess->usertree, user, &pos);
-	tree_remove (sess->usertree_alpha, user, &pos);
+	fe_userlist_remove (sess, user);
 
 	/* which bit number is affected? */
 	access = mode_access (sess->server, mode, &prefix);
@@ -318,11 +291,8 @@ userlist_update_mode (session *sess, char *name, char mode, char sign)
 	update_counts (sess, user, prefix, level, offset);
 
 	/* insert it back into its new place */
-	tree_insert (sess->usertree_alpha, user);
-	pos = tree_insert (sess->usertree, user);
-
-	/* let GTK move it too */
-	fe_userlist_move (sess, user, pos);
+	tree_insert (sess->usertree, user);
+	fe_userlist_insert (sess, user, FALSE);
 	fe_userlist_numbers (sess);
 }
 
@@ -335,14 +305,12 @@ userlist_change (struct session *sess, char *oldname, char *newname)
 	if (user)
 	{
 		tree_remove (sess->usertree, user, &pos);
-		tree_remove (sess->usertree_alpha, user, &pos);
+		fe_userlist_remove (sess, user);
 
 		safe_strcpy (user->nick, newname, NICKLEN);
 
-		tree_insert (sess->usertree_alpha, user);
-
-		fe_userlist_move (sess, user, tree_insert (sess->usertree, user));
-		fe_userlist_numbers (sess);
+		tree_insert (sess->usertree, user);
+		fe_userlist_insert (sess, user, FALSE);
 
 		return 1;
 	}
@@ -381,7 +349,6 @@ userlist_remove_user (struct session *sess, struct User *user)
 		sess->me = NULL;
 
 	tree_remove (sess->usertree, user, &pos);
-	tree_remove (sess->usertree_alpha, user, &pos);
 	free_user (user, NULL);
 }
 
@@ -397,8 +364,7 @@ userlist_add (struct session *sess, char *name, char *hostname,
 
 	notify_set_online (sess->server, name + prefix_chars, tags_data);
 
-	user = malloc (sizeof (struct User));
-	memset (user, 0, sizeof (struct User));
+	user = g_new0 (struct User, 1);
 
 	user->access = acc;
 
@@ -408,7 +374,7 @@ userlist_add (struct session *sess, char *name, char *hostname,
 
 	/* add it to our linked list */
 	if (hostname)
-		user->hostname = strdup (hostname);
+		user->hostname = g_strdup (hostname);
 	safe_strcpy (user->nick, name + prefix_chars, NICKLEN);
 	/* is it me? */
 	if (!sess->server->p_cmp (user->nick, sess->server->nick))
@@ -417,9 +383,9 @@ userlist_add (struct session *sess, char *name, char *hostname,
 	if (sess->server->have_extjoin)
 	{
 		if (account && *account)
-			user->account = strdup (account);
+			user->account = g_strdup (account);
 		if (realname && *realname)
-			user->realname = strdup (realname);
+			user->realname = g_strdup (realname);
 	}
 
 	row = userlist_insertname (sess, user);
@@ -427,13 +393,10 @@ userlist_add (struct session *sess, char *name, char *hostname,
 	/* duplicate? some broken servers trigger this */
 	if (row == -1)
 	{
-		if (user->hostname)
-			free (user->hostname);
-		if (user->account)
-			free (user->account);
-		if (user->realname)
-			free (user->realname);
-		free (user);
+		g_free (user->hostname);
+		g_free (user->account);
+		g_free (user->realname);
+		g_free (user);
 		return;
 	}
 
@@ -451,7 +414,7 @@ userlist_add (struct session *sess, char *name, char *hostname,
 	if (user->me)
 		sess->me = user;
 
-	fe_userlist_insert (sess, user, row, FALSE);
+	fe_userlist_insert (sess, user, FALSE);
 	fe_userlist_numbers (sess);
 }
 
@@ -465,7 +428,7 @@ rehash_cb (struct User *user, session *sess)
 void
 userlist_rehash (session *sess)
 {
-	tree_foreach (sess->usertree_alpha, (tree_traverse_func *)rehash_cb, sess);
+	tree_foreach (sess->usertree, (tree_traverse_func *)rehash_cb, sess);
 }
 
 static int
@@ -480,7 +443,7 @@ userlist_flat_list (session *sess)
 {
 	GSList *list = NULL;
 
-	tree_foreach (sess->usertree_alpha, (tree_traverse_func *)flat_cb, &list);
+	tree_foreach (sess->usertree, (tree_traverse_func *)flat_cb, &list);
 	return g_slist_reverse (list);
 }
 
@@ -496,6 +459,6 @@ userlist_double_list(session *sess)
 {
 	GList *list = NULL;
 
-	tree_foreach (sess->usertree_alpha, (tree_traverse_func *)double_cb, &list);
+	tree_foreach (sess->usertree, (tree_traverse_func *)double_cb, &list);
 	return list;
 }
diff --git a/src/common/userlist.h b/src/common/userlist.h
index ebf95606..0c53dc71 100644
--- a/src/common/userlist.h
+++ b/src/common/userlist.h
@@ -61,5 +61,7 @@ void userlist_update_mode (session *sess, char *name, char mode, char sign);
 GSList *userlist_flat_list (session *sess);
 GList *userlist_double_list (session *sess);
 void userlist_rehash (session *sess);
+int nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2);
+int nick_cmp_alpha (struct User *user1, struct User *user2, server *serv);
 
 #endif
diff --git a/src/common/util.c b/src/common/util.c
index b5ee1af2..be3dcac2 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -31,7 +31,6 @@
 
 #ifdef WIN32
 #include <sys/timeb.h>
-#include <process.h>
 #include <io.h>
 #include <VersionHelpers.h>
 #else
@@ -41,7 +40,7 @@
 #include <sys/utsname.h>
 #endif
 
-#include "../../config.h"
+#include "config.h"
 #include <fcntl.h>
 #include <errno.h>
 #include "hexchat.h"
@@ -52,9 +51,6 @@
 #if defined (USING_FREEBSD) || defined (__APPLE__)
 #include <sys/sysctl.h>
 #endif
-#ifdef SOCKS
-#include <socks.h>
-#endif
 
 /* SASL mechanisms */
 #ifdef USE_OPENSSL
@@ -67,10 +63,6 @@
 #endif
 #endif
 
-#ifndef HAVE_SNPRINTF
-#define snprintf g_snprintf
-#endif
-
 char *
 file_part (char *file)
 {
@@ -254,11 +246,11 @@ expand_homedir (char *file)
 
 	if (file[0] == '~')
 	{
+		char *slash_pos;
+
 		if (file[1] == '\0' || file[1] == '/')
 			return g_strconcat (g_get_home_dir (), &file[1], NULL);
 
-		char *slash_pos;
-
 		user = g_strdup(file);
 
 		slash_pos = strchr(user, '/');
@@ -370,13 +362,13 @@ strip_hidden_attribute (char *src, char *dst)
 	return len;
 }
 
-#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__)
+#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__) || defined (__CYGWIN__)
 
 static void
 get_cpu_info (double *mhz, int *cpus)
 {
 
-#ifdef USING_LINUX
+#if defined(USING_LINUX) || defined (__CYGWIN__)
 
 	char buf[256];
 	int fh;
@@ -508,7 +500,22 @@ get_sys_str (int with_cpu)
 	static char winver[20];
 	double mhz;
 
-	if (IsWindows8Point1OrGreater ())
+	/* Broken since major bumped to 10, should start to work eventually.
+	 * No, IsWindowsVersionOrGreater (10, 0, 0) doesn't work either.
+	 * TODO: replace with IsWindows10OrGreater() once added to the SDK.
+	 */
+	if (IsWindowsVersionOrGreater (6, 4, 0))
+	{
+		if (IsWindowsServer ())
+		{
+			strcpy (winver, "Server 10");
+		}
+		else
+		{
+			strcpy (winver, "10");
+		}
+	}
+	else if (IsWindows8Point1OrGreater ())
 	{
 		if (IsWindowsServer ())
 		{
@@ -610,7 +617,7 @@ get_sys_str (int with_cpu)
 char *
 get_sys_str (int with_cpu)
 {
-#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__)
+#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__) || defined (__CYGWIN__)
 	double mhz;
 #endif
 	int cpus = 1;
@@ -620,24 +627,24 @@ get_sys_str (int with_cpu)
 	if (buf)
 		return buf;
 
-	buf = malloc (128);
-
 	uname (&un);
 
-#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__)
+#if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__) || defined (__CYGWIN__)
 	get_cpu_info (&mhz, &cpus);
 	if (mhz && with_cpu)
 	{
 		double cpuspeed = ( mhz > 1000 ) ? mhz / 1000 : mhz;
 		const char *cpuspeedstr = ( mhz > 1000 ) ? "GHz" : "MHz";
-		snprintf (buf, 128,
-					(cpus == 1) ? "%s %s [%s/%.2f%s]" : "%s %s [%s/%.2f%s/SMP]",
-					un.sysname, un.release, un.machine,
-					cpuspeed, cpuspeedstr);
+		buf = g_strdup_printf (
+			(cpus == 1) ? "%s %s [%s/%.2f%s]" : "%s %s [%s/%.2f%s/SMP]",
+			un.sysname, un.release, un.machine,
+			cpuspeed, cpuspeedstr);
 	}
 	else
+		buf = g_strdup_printf ("%s %s", un.sysname, un.release);
+#else
+	buf = g_strdup_printf ("%s %s", un.sysname, un.release);
 #endif
-		snprintf (buf, 128, "%s %s", un.sysname, un.release);
 
 	return buf;
 }
@@ -1217,80 +1224,6 @@ const unsigned char rfc_tolowertab[] =
 	0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
 };
 
-/*static unsigned char touppertab[] =
-	{ 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
-	0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
-	0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
-	0x1e, 0x1f,
-	' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
-	'*', '+', ',', '-', '.', '/',
-	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-	':', ';', '<', '=', '>', '?',
-	'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
-	'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
-	'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
-	0x5f,
-	'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
-	'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
-	'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
-	0x7f,
-	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
-	0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-	0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
-	0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
-	0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
-	0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
-	0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
-	0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
-	0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
-};*/
-
-/*static int
-rename_utf8 (char *oldname, char *newname)
-{
-	int sav, res;
-	char *fso, *fsn;
-
-	fso = hexchat_filename_from_utf8 (oldname, -1, 0, 0, 0);
-	if (!fso)
-		return FALSE;
-	fsn = hexchat_filename_from_utf8 (newname, -1, 0, 0, 0);
-	if (!fsn)
-	{
-		g_free (fso);
-		return FALSE;
-	}
-
-	res = rename (fso, fsn);
-	sav = errno;
-	g_free (fso);
-	g_free (fsn);
-	errno = sav;
-	return res;
-}
-
-static int
-unlink_utf8 (char *fname)
-{
-	int res;
-	char *fs;
-
-	fs = hexchat_filename_from_utf8 (fname, -1, 0, 0, 0);
-	if (!fs)
-		return FALSE;
-
-	res = unlink (fs);
-	g_free (fs);
-	return res;
-}*/
-
 static gboolean
 file_exists (char *fname)
 {
@@ -1526,7 +1459,7 @@ canonalize_key (char *key)
 }
 
 int
-portable_mode ()
+portable_mode (void)
 {
 #ifdef WIN32
 	if ((_access( "portable-mode", 0 )) != -1)
@@ -1543,7 +1476,7 @@ portable_mode ()
 }
 
 int
-unity_mode ()
+unity_mode (void)
 {
 #ifdef G_OS_UNIX
 	const char *env = g_getenv("XDG_CURRENT_DESKTOP");
@@ -1578,7 +1511,7 @@ parse_dh (char *str, DH **dh_out, unsigned char **secret_out, int *keysize_out)
 {
 	DH *dh;
 	guchar *data, *decoded_data;
-	guchar *secret;
+	guchar *secret = NULL;
 	gsize data_len;
 	guint size;
 	guint16 size16;
@@ -1630,7 +1563,7 @@ parse_dh (char *str, DH **dh_out, unsigned char **secret_out, int *keysize_out)
 	if (!(DH_generate_key (dh)))
 		goto fail;
 
-	secret = (unsigned char*)malloc (DH_size(dh));
+	secret = g_malloc (DH_size (dh));
 	key_size = DH_compute_key (secret, pubkey, dh);
 	if (key_size == -1)
 		goto fail;
@@ -1643,8 +1576,9 @@ parse_dh (char *str, DH **dh_out, unsigned char **secret_out, int *keysize_out)
 	return 1;
 
 fail:
-	if (decoded_data)
-		g_free (decoded_data);
+	g_free (secret);
+	g_free (decoded_data);
+
 	return 0;
 }
 
@@ -1652,7 +1586,7 @@ char *
 encode_sasl_pass_blowfish (char *user, char *pass, char *data)
 {
 	DH *dh;
-	char *response, *ret;
+	char *response, *ret = NULL;
 	unsigned char *secret;
 	unsigned char *encrypted_pass;
 	char *plain_pass;
@@ -1667,11 +1601,9 @@ encode_sasl_pass_blowfish (char *user, char *pass, char *data)
 		return NULL;
 	BF_set_key (&key, key_size, secret);
 
-	encrypted_pass = (guchar*)malloc (pass_len);
-	memset (encrypted_pass, 0, pass_len);
-	plain_pass = (char*)malloc (pass_len);
-	memset (plain_pass, 0, pass_len);
-	memcpy (plain_pass, pass, pass_len);
+	encrypted_pass = g_malloc0 (pass_len);
+	plain_pass = g_malloc0 (pass_len);
+	memcpy (plain_pass, pass, strlen(pass));
 	out_ptr = (char*)encrypted_pass;
 	in_ptr = (char*)plain_pass;
 
@@ -1680,7 +1612,7 @@ encode_sasl_pass_blowfish (char *user, char *pass, char *data)
 
 	/* Create response */
 	length = 2 + BN_num_bytes (dh->pub_key) + pass_len + user_len + 1;
-	response = (char*)malloc (length);
+	response = g_malloc0 (length);
 	out_ptr = response;
 
 	/* our key */
@@ -1699,11 +1631,12 @@ encode_sasl_pass_blowfish (char *user, char *pass, char *data)
 	
 	ret = g_base64_encode ((const guchar*)response, length);
 
-	DH_free (dh);
-	free (plain_pass);
-	free (encrypted_pass);
-	free (secret);
-	free (response);
+	g_free (response);
+
+	DH_free(dh);
+	g_free (plain_pass);
+	g_free (encrypted_pass);
+	g_free (secret);
 
 	return ret;
 }
@@ -1729,10 +1662,8 @@ encode_sasl_pass_aes (char *user, char *pass, char *data)
 	if (!parse_dh (data, &dh, &secret, &key_size))
 		return NULL;
 
-	encrypted_userpass = (guchar*)malloc (userpass_len);
-	memset (encrypted_userpass, 0, userpass_len);
-	plain_userpass = (guchar*)malloc (userpass_len);
-	memset (plain_userpass, 0, userpass_len);
+	encrypted_userpass = g_malloc0 (userpass_len);
+	plain_userpass = g_malloc0 (userpass_len);
 
 	/* create message */
 	/* format of: <username>\0<password>\0<padding> */
@@ -1763,7 +1694,7 @@ encode_sasl_pass_aes (char *user, char *pass, char *data)
 	/* Create response */
 	/* format of:  <size pubkey><pubkey><iv (always 16 bytes)><ciphertext> */
 	length = 2 + key_size + sizeof(iv) + userpass_len;
-	response = (char*)malloc (length);
+	response = g_malloc (length);
 	out_ptr = response;
 
 	/* our key */
@@ -1784,11 +1715,10 @@ encode_sasl_pass_aes (char *user, char *pass, char *data)
 
 end:
 	DH_free (dh);
-	free (plain_userpass);
-	free (encrypted_userpass);
-	free (secret);
-	if (response)
-		free (response);
+	g_free (plain_userpass);
+	g_free (encrypted_userpass);
+	g_free (secret);
+	g_free (response);
 
 	return ret;
 }
@@ -1866,9 +1796,7 @@ challengeauth_response (char *username, char *password, char *challenge)
 		g_string_append_printf (buf, "%02x", (unsigned int) digest[i]);
 	}
 
-	digest = (unsigned char *) g_string_free (buf, FALSE);
-
-	return (char *) digest;
+	return g_string_free (buf, FALSE);
 }
 #endif
 
diff --git a/src/common/util.h b/src/common/util.h
index 5231e56d..2c9f790c 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -73,12 +73,12 @@ guint32 str_hash (const char *key);
 guint32 str_ihash (const unsigned char *key);
 void safe_strcpy (char *dest, const char *src, int bytes_left);
 void canonalize_key (char *key);
-int portable_mode ();
-int unity_mode ();
+int portable_mode (void);
+int unity_mode (void);
 char *encode_sasl_pass_plain (char *user, char *pass);
 char *encode_sasl_pass_blowfish (char *user, char *pass, char *data);
 char *encode_sasl_pass_aes (char *user, char *pass, char *data);
 char *challengeauth_response (char *username, char *password, char *challenge);
 size_t strftime_validated (char *dest, size_t destsize, const char *format, const struct tm *time);
-size_t strftime_utf8 (char *dest, size_t destsize, const char *format, time_t time);
+gsize strftime_utf8 (char *dest, gsize destsize, const char *format, time_t time);
 #endif