summary refs log tree commit diff stats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Make.plugin38
-rw-r--r--plugins/checksum/Makefile.am6
-rw-r--r--plugins/checksum/checksum.c274
-rw-r--r--plugins/checksum/checksum.vcxproj64
-rw-r--r--plugins/doat/Makefile.am6
-rw-r--r--plugins/doat/doat.c18
-rw-r--r--plugins/doat/doat.vcxproj68
-rw-r--r--plugins/exec/exec.vcxproj60
-rw-r--r--plugins/fishlim/Makefile.am8
-rw-r--r--plugins/fishlim/fish.c44
-rw-r--r--plugins/fishlim/fish.h3
-rw-r--r--plugins/fishlim/fishlim.vcxproj66
-rw-r--r--plugins/fishlim/fishlim.vcxproj.filters6
-rw-r--r--plugins/fishlim/irc.c54
-rw-r--r--plugins/fishlim/irc.h5
-rw-r--r--plugins/fishlim/keystore.c92
-rw-r--r--plugins/fishlim/keystore.h9
-rw-r--r--plugins/fishlim/misc.c54
-rw-r--r--plugins/fishlim/misc.h36
-rw-r--r--plugins/fishlim/plugin_hexchat.c137
-rw-r--r--plugins/fishlim/plugin_hexchat.h1
-rw-r--r--plugins/fishlim/test.c94
-rw-r--r--plugins/mpcinfo/functions.c105
-rw-r--r--plugins/mpcinfo/mp3Info.c102
-rw-r--r--plugins/mpcinfo/mpcInfo.c27
-rw-r--r--plugins/mpcinfo/mpcinfo.vcxproj68
-rw-r--r--plugins/mpcinfo/oggInfo.c20
-rw-r--r--plugins/mpcinfo/theme.c44
-rw-r--r--plugins/perl/Makefile.am11
-rw-r--r--plugins/perl/perl.c127
-rw-r--r--plugins/perl/perl.vcxproj78
-rw-r--r--plugins/plugin-conf.in19
-rw-r--r--plugins/python/Makefile.am8
-rw-r--r--plugins/python/python.c166
-rw-r--r--plugins/python/python2.vcxproj68
-rw-r--r--plugins/python/python3.vcxproj68
-rw-r--r--plugins/sysinfo/Makefile.am18
-rw-r--r--plugins/sysinfo/format.c90
-rw-r--r--plugins/sysinfo/format.h (renamed from plugins/sysinfo/xsys.h)18
-rw-r--r--plugins/sysinfo/hwmon.c63
-rw-r--r--plugins/sysinfo/match.c240
-rw-r--r--plugins/sysinfo/osx/backend.m263
-rw-r--r--plugins/sysinfo/pci.c156
-rw-r--r--plugins/sysinfo/shared/df.c53
-rw-r--r--plugins/sysinfo/shared/df.h23
-rw-r--r--plugins/sysinfo/sysinfo-backend.h33
-rw-r--r--plugins/sysinfo/sysinfo.c277
-rw-r--r--plugins/sysinfo/sysinfo.cpp416
-rw-r--r--plugins/sysinfo/sysinfo.h (renamed from plugins/sysinfo/hwmon.h)15
-rw-r--r--plugins/sysinfo/sysinfo.vcxproj84
-rw-r--r--plugins/sysinfo/sysinfo.vcxproj.filters22
-rw-r--r--plugins/sysinfo/unix/backend.c170
-rw-r--r--plugins/sysinfo/unix/match.c98
-rw-r--r--plugins/sysinfo/unix/match.h (renamed from plugins/sysinfo/match.h)6
-rw-r--r--plugins/sysinfo/unix/parse.c (renamed from plugins/sysinfo/parse.c)271
-rw-r--r--plugins/sysinfo/unix/parse.h (renamed from plugins/sysinfo/parse.h)9
-rw-r--r--plugins/sysinfo/unix/pci.c169
-rw-r--r--plugins/sysinfo/unix/pci.h (renamed from plugins/sysinfo/pci.h)0
-rw-r--r--plugins/sysinfo/win32/backend.c493
-rw-r--r--plugins/sysinfo/xsys-changelog116
-rw-r--r--plugins/sysinfo/xsys-install15
-rw-r--r--plugins/sysinfo/xsys-makefile38
-rw-r--r--plugins/sysinfo/xsys-readme105
-rw-r--r--plugins/sysinfo/xsys.c923
-rw-r--r--plugins/upd/upd.c236
-rw-r--r--plugins/upd/upd.vcxproj74
-rw-r--r--plugins/winamp/winamp.c215
-rw-r--r--plugins/winamp/winamp.vcxproj70
68 files changed, 2559 insertions, 4274 deletions
diff --git a/plugins/Make.plugin b/plugins/Make.plugin
deleted file mode 100644
index 4a4c56fd..00000000
--- a/plugins/Make.plugin
+++ /dev/null
@@ -1,38 +0,0 @@
-# Makefile stub for creating standalone plugin distributions.
-
-plugin_dist: pg_dist pg_dist/config.status
-	pgi=`cd $(srcdir)/.. && pwd`; cd pg_dist; \
-		$(MAKE) $(AM_MAKEFLAGS) PLUGIN_INCLUDES=-I$$pgi distcheck dist
-
-pg_dist: pg_distdir pg_dist/configure.in pg_dist/install-sh
-	cd pg_dist \
-	&& libtoolize --copy --force --automake \
-	&& automake --copy --add-missing --foreign \
-	&& autoconf -l ../$(top_srcdir)
-
-pg_distdir: $(DISTFILES)
-	test -d pg_dist || mkdir pg_dist
-	for dfile in $(DISTFILES); do \
-		test -f $$dfile && cp $$dfile pg_dist \
-		|| test -f $(srcdir)/$$dfile && cp $(srcdir)/$$dfile pg_dist; done
-	sed '/Make.plugin/d' < $(srcdir)/Makefile.am > pg_dist/Makefile.am
-
-pg_dist/configure.in: $(srcdir)/../plugin-conf.in
-	rm -f pg_dist/configure.in
-	test -f $(srcdir)/config.stub \
-	&& cat $(srcdir)/config.stub > pg_dist/configure.in || true
-	cat $(srcdir)/../plugin-conf.in | \
-		sed 's%@PLUGIN_VERSION@%$(PLUGIN_VERSION)%; \
-		s%@PLUGIN@%$(PLUGIN)%' >> pg_dist/configure.in
-
-pg_dist/install-sh: pg_distdir
-	cp $(top_srcdir)/install-sh pg_dist
-
-pg_dist/config.status: pg_dist/configure
-	cd pg_dist \
-	&& test -f config.status && $(SHELL) ./config.status --recheck \
-	|| $(SHELL) ./configure --enable-maintainer-mode
-
-DISTCLEANFILES = pg_dist/* pg_dist
-
-#
diff --git a/plugins/checksum/Makefile.am b/plugins/checksum/Makefile.am
index 419c762f..4e911f28 100644
--- a/plugins/checksum/Makefile.am
+++ b/plugins/checksum/Makefile.am
@@ -2,6 +2,6 @@ libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = checksum.la
 checksum_la_SOURCES = checksum.c
-checksum_la_LDFLAGS = -avoid-version -module 
-checksum_la_LIBADD = 
-AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+checksum_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+checksum_la_LIBADD = $(GLIB_LIBS)
+checksum_la_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)/src/common
diff --git a/plugins/checksum/checksum.c b/plugins/checksum/checksum.c
index 6ace8543..9a7f0ebd 100644
--- a/plugins/checksum/checksum.c
+++ b/plugins/checksum/checksum.c
@@ -20,222 +20,194 @@
  * THE SOFTWARE.
  */
 
-#ifdef __APPLE__
-#define __AVAILABILITYMACROS__
-#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#endif
+#include "config.h"
 
-#include <stdio.h>
-#include <string.h>
 #include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <openssl/sha.h>
 #include <glib.h>
-
-#ifdef WIN32
-#ifndef snprintf
-#define snprintf _snprintf
-#endif
-#define stat _stat64
-#else
-/* for INT_MAX */
-#include <limits.h>
-#define __USE_LARGEFILE64
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-#endif
+#include <glib/gstdio.h>
+#include <gio/gio.h>
 
 #include "hexchat-plugin.h"
 
 #define BUFSIZE 32768
 #define DEFAULT_LIMIT 256									/* default size is 256 MiB */
+#define SHA256_DIGEST_LENGTH 32
+#define SHA256_BUFFER_LENGTH 65
 
 static hexchat_plugin *ph;									/* plugin handle */
 static char name[] = "Checksum";
 static char desc[] = "Calculate checksum for DCC file transfers";
 static char version[] = "3.1";
 
-/* Use of OpenSSL SHA256 interface: http://adamlamers.com/?p=5 */
 static void
-sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65])
+set_limit (char *size)
 {
-	int i;
-	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
+	int limit = atoi (size);
+
+	if (limit > 0 && limit < INT_MAX)
 	{
-		sprintf (outputBuffer + (i * 2), "%02x", hash[i]);
+		if (hexchat_pluginpref_set_int (ph, "limit", limit))
+			hexchat_printf (ph, "Checksum: File size limit has successfully been set to: %d MiB\n", limit);
+		else
+			hexchat_printf (ph, "Checksum: File access error while saving!\n");
 	}
-	outputBuffer[64] = 0;
-}
-
-#if 0
-static void
-sha256 (char *string, char outputBuffer[65])
-{
-	int i;
-	unsigned char hash[SHA256_DIGEST_LENGTH];
-	SHA256_CTX sha256;
-
-	SHA256_Init (&sha256);
-	SHA256_Update (&sha256, string, strlen (string));
-	SHA256_Final (hash, &sha256);
-
-	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
+	else
 	{
-		sprintf (outputBuffer + (i * 2), "%02x", hash[i]);
+		hexchat_printf (ph, "Checksum: Invalid input!\n");
 	}
-	outputBuffer[64] = 0;
 }
-#endif
 
 static int
-sha256_file (char *path, char outputBuffer[65])
+get_limit ()
 {
-	int bytesRead;
-	unsigned char *buffer;
-	unsigned char hash[SHA256_DIGEST_LENGTH];
-	SHA256_CTX sha256;
+	int size = hexchat_pluginpref_get_int (ph, "limit");
 
-	FILE *file = fopen (path, "rb");
-	if (!file)
-	{
-		return -534;
-	}
+	if (size <= 0 || size >= INT_MAX)
+		return DEFAULT_LIMIT;
+	else
+		return size;
+}
 
-	SHA256_Init (&sha256);
-	buffer = malloc (BUFSIZE);
-	bytesRead = 0;
+static gboolean
+check_limit (GFile *file)
+{
+	GFileInfo *file_info;
+	goffset file_size;
 
-	if (!buffer)
-	{
-		fclose (file);
-		return ENOMEM;
-	}
+	file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE,
+									NULL, NULL);
 
-	while ((bytesRead = fread (buffer, 1, BUFSIZE, file)))
-	{
-		SHA256_Update (&sha256, buffer, bytesRead);
-	}
+	if (!file_info)
+		return FALSE;
 
-	SHA256_Final (hash, &sha256);
-	sha256_hash_string (hash, outputBuffer);
+	file_size = g_file_info_get_size (file_info);
+	g_object_unref (file_info);
 
-	fclose (file);
-	free (buffer);
-	return 0;
+	if (file_size > get_limit () * 1048576ll)
+		return FALSE;
+
+	return TRUE;
 }
 
-static void
-set_limit (char* size)
+static gboolean
+sha256_from_stream (GFileInputStream *file_stream, char out_buf[])
 {
-	int buffer = atoi (size);
+	GChecksum *checksum;
+	gssize bytes_read;
+	guint8 digest[SHA256_DIGEST_LENGTH];
+	gsize digest_len = sizeof(digest);
+	guchar buffer[BUFSIZE];
+	gsize i;
+
+	checksum = g_checksum_new (G_CHECKSUM_SHA256);
 
-	if (buffer > 0 && buffer < INT_MAX)
+	while ((bytes_read = g_input_stream_read (G_INPUT_STREAM (file_stream), buffer, sizeof (buffer), NULL, NULL)))
 	{
-		if (hexchat_pluginpref_set_int (ph, "limit", buffer))
-		{
-			hexchat_printf (ph, "File size limit has successfully been set to: %d MiB\n", buffer);
-		}
-		else
+		if (bytes_read == -1)
 		{
-			hexchat_printf (ph, "File access error while saving!\n");
+			g_checksum_free (checksum);
+			return FALSE;
 		}
+
+		g_checksum_update (checksum, buffer, bytes_read);
 	}
-	else
+
+	g_checksum_get_digest (checksum, digest, &digest_len);
+	g_checksum_free (checksum);
+
+	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
 	{
-		hexchat_printf (ph, "Invalid input!\n");
+		/* out_buf will be exactly SHA256_BUFFER_LENGTH including null */
+		g_sprintf (out_buf + (i * 2), "%02x", digest[i]);
 	}
+
+	return TRUE;
 }
 
-static int
-get_limit ()
+static gboolean
+sha256_from_file (char *filename, char out_buf[])
 {
-	int size = hexchat_pluginpref_get_int (ph, "limit");
+	GFileInputStream *file_stream;
+	char *filename_fs;
+	GFile *file;
 
-	if (size <= -1 || size >= INT_MAX)
+	filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
+	if (!filename_fs)
 	{
-		return DEFAULT_LIMIT;
+		hexchat_printf (ph, "Checksum: Invalid filename (%s)\n", filename);
+		return FALSE;
 	}
-	else
+
+	file = g_file_new_for_path (filename_fs);
+	g_free (filename_fs);
+	if (!file)
 	{
-		return size;
+		hexchat_printf (ph, "Checksum: Failed to open %s\n", filename);
+		return FALSE;
 	}
-}
-
-static void
-print_limit ()
-{
-	hexchat_printf (ph, "File size limit for checksums: %d MiB", get_limit ());
-}
 
-static int
-dccrecv_cb (char *word[], void *userdata)
-{
-	int result;
-	struct stat buffer;									/* buffer for storing file info */
-	char sum[65];											/* buffer for checksum */
-	const char *file;
-	char *cfile;
-
-	if (hexchat_get_prefs (ph, "dcc_completed_dir", &file, NULL) == 1 && file[0] != 0)
+	if (!check_limit (file))
 	{
-		cfile = g_strconcat (file, G_DIR_SEPARATOR_S, word[1], NULL);
+		hexchat_printf (ph, "Checksum: %s is larger than size limit. You can increase it with /CHECKSUM SET.\n", filename);
+		g_object_unref (file);
+		return FALSE;
 	}
-	else
+
+	file_stream = g_file_read (file, NULL, NULL);
+	if (!file_stream)
 	{
-		cfile = g_strdup(word[2]);
+		hexchat_printf (ph, "Checksum: Failed to read file %s\n", filename);
+		g_object_unref (file);
+		return FALSE;
 	}
 
-	result = stat (cfile, &buffer);
-	if (result == 0)										/* stat returns 0 on success */
+	if (!sha256_from_stream (file_stream, out_buf))
 	{
-		if (buffer.st_size <= (unsigned long long) get_limit () * 1048576)
-		{
-			sha256_file (cfile, sum);						/* file is the full filename even if completed dir set */
-			/* try to print the checksum in the privmsg tab of the sender */
-			hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
-			hexchat_printf (ph, "SHA-256 checksum for %s (local):  %s\n", word[1], sum);
-		}
-		else
-		{
-			hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
-			hexchat_printf (ph, "SHA-256 checksum for %s (local):  (size limit reached, no checksum calculated, you can increase it with /CHECKSUM INC)\n", word[1]);
-		}
+		hexchat_printf (ph, "Checksum: Failed to generate checksum for %s\n", filename);
+		g_object_unref (file_stream);
+		g_object_unref (file);
+		return FALSE;
 	}
+
+	g_object_unref (file_stream);
+	g_object_unref (file);
+	return TRUE;
+}
+
+static int
+dccrecv_cb (char *word[], void *userdata)
+{
+	const char *dcc_completed_dir;
+	char *filename, checksum[SHA256_BUFFER_LENGTH];
+
+	/* Print in the privmsg tab of the sender */
+	hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
+
+	if (hexchat_get_prefs (ph, "dcc_completed_dir", &dcc_completed_dir, NULL) == 1 && dcc_completed_dir[0] != '\0')
+		filename = g_build_filename (dcc_completed_dir, word[1], NULL);
 	else
+		filename = g_strdup (word[2]);
+
+	if (sha256_from_file (filename, checksum))
 	{
-		hexchat_printf (ph, "File access error!\n");
+		hexchat_printf (ph, "SHA-256 checksum for %s (local): %s\n", word[1], checksum);
 	}
 
-	g_free (cfile);
+	g_free (filename);
 	return HEXCHAT_EAT_NONE;
 }
 
 static int
 dccoffer_cb (char *word[], void *userdata)
 {
-	int result;
-	struct stat buffer;									/* buffer for storing file info */
-	char sum[65];											/* buffer for checksum */
+	char checksum[SHA256_BUFFER_LENGTH];
 
-	result = stat (word[3], &buffer);
-	if (result == 0)										/* stat returns 0 on success */
-	{
-		if (buffer.st_size <= (unsigned long long) get_limit () * 1048576)
-		{
-			sha256_file (word[3], sum);						/* word[3] is the full filename */
-			hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], sum);
-		}
-		else
-		{
-			hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
-			hexchat_printf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): (size limit reached, no checksum calculated)", word[2], word[1]);
-		}
-	}
-	else
+	/* Print in the privmsg tab of the receiver */
+	hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
+
+	if (sha256_from_file (word[3], checksum))
 	{
-		hexchat_printf (ph, "File access error!\n");
+		hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], checksum);
 	}
 
 	return HEXCHAT_EAT_NONE;
@@ -246,7 +218,7 @@ checksum (char *word[], char *word_eol[], void *userdata)
 {
 	if (!g_ascii_strcasecmp ("GET", word[2]))
 	{
-		print_limit ();
+		hexchat_printf (ph, "File size limit for checksums: %d MiB", get_limit ());
 	}
 	else if (!g_ascii_strcasecmp ("SET", word[2]))
 	{
@@ -259,7 +231,7 @@ checksum (char *word[], char *word_eol[], void *userdata)
 		hexchat_printf (ph, "  SET <filesize> - set the maximum file size (in MiB) to be hashed\n");
 	}
 
-	return HEXCHAT_EAT_NONE;
+	return HEXCHAT_EAT_ALL;
 }
 
 int
@@ -277,7 +249,7 @@ hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **p
 		hexchat_pluginpref_set_int (ph, "limit", DEFAULT_LIMIT);
 	}
 
-	hexchat_hook_command (ph, "CHECKSUM", HEXCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|SET", 0);
+	hexchat_hook_command (ph, "CHECKSUM", HEXCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|SET", NULL);
 	hexchat_hook_print (ph, "DCC RECV Complete", HEXCHAT_PRI_NORM, dccrecv_cb, NULL);
 	hexchat_hook_print (ph, "DCC Offer", HEXCHAT_PRI_NORM, dccoffer_cb, NULL);
 
diff --git a/plugins/checksum/checksum.vcxproj b/plugins/checksum/checksum.vcxproj
index 7838cb4a..948295a0 100644
--- a/plugins/checksum/checksum.vcxproj
+++ b/plugins/checksum/checksum.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>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,57 +20,19 @@
     <RootNamespace>checksum</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</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>

-    <TargetName>hcchecksum</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcchecksum</TargetName>

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

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

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CHECKSUM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>checksum.def</ModuleDefinitionFile>

       <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

@@ -77,19 +40,10 @@
   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;CHECKSUM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>checksum.def</ModuleDefinitionFile>

       <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

@@ -102,6 +56,4 @@
     <None Include="checksum.def" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/doat/Makefile.am b/plugins/doat/Makefile.am
index abfca29e..a04d2863 100644
--- a/plugins/doat/Makefile.am
+++ b/plugins/doat/Makefile.am
@@ -2,7 +2,7 @@ libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = doat.la
 doat_la_SOURCES = doat.c
-doat_la_LDFLAGS = -avoid-version -module 
-doat_la_LIBADD = 
-AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+doat_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+doat_la_LIBADD = $(GLIB_LIBS)
+doat_la_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)/src/common
 
diff --git a/plugins/doat/doat.c b/plugins/doat/doat.c
index 194be1a3..1d1bfcdf 100644
--- a/plugins/doat/doat.c
+++ b/plugins/doat/doat.c
@@ -5,9 +5,12 @@
  * http://sam.zoy.org/wtfpl/COPYING or http://lwsitu.com/xchat/COPYING
  * for more details. */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <glib.h>
 #include "hexchat-plugin.h"
 
 static hexchat_plugin *ph;
@@ -31,7 +34,7 @@ parse_command( char *word[], char *word_eol[], void *userdata ) {
 				break;
 			}
 
-			channel = strdup( token );
+			channel = g_strdup( token );
 				
 			delimiter = strchr( channel, '/' );
 
@@ -40,13 +43,13 @@ parse_command( char *word[], char *word_eol[], void *userdata ) {
 				*delimiter = '\0';
 
 				if( strlen( delimiter + 1 ) > 0 ) {
-					server = strdup( delimiter + 1 );
+					server = g_strdup( delimiter + 1 );
 				}
 			}
 
 			/* /Network form */
 			if( strlen( channel ) == 0 ) {
-				free( channel );
+				g_free( channel );
 				channel = NULL;
 			}
 
@@ -58,13 +61,8 @@ parse_command( char *word[], char *word_eol[], void *userdata ) {
 				}
 			}
 
-			if( channel != NULL ) {
-				free( channel );
-			}
-
-			if( server != NULL ) {
-				free( server );
-			}
+			g_free( channel );
+			g_free( server );
 		}
 	}
 	return HEXCHAT_EAT_HEXCHAT;
diff --git a/plugins/doat/doat.vcxproj b/plugins/doat/doat.vcxproj
index 171e2b0d..ae44d7f8 100644
--- a/plugins/doat/doat.vcxproj
+++ b/plugins/doat/doat.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>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,75 +20,32 @@
     <RootNamespace>doat</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</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>

-    <TargetName>hcdoat</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcdoat</TargetName>

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

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

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;DOAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>..\..\src\common;$(HexChatLib);$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>doat.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;DOAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>..\..\src\common;$(HexChatLib);$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>doat.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

@@ -98,6 +56,4 @@
     <None Include="doat.def" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/exec/exec.vcxproj b/plugins/exec/exec.vcxproj
index a04c0046..d691bb11 100644
--- a/plugins/exec/exec.vcxproj
+++ b/plugins/exec/exec.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>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,75 +20,28 @@
     <RootNamespace>exec</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</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>

-    <TargetName>hcexec</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcexec</TargetName>

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

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

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXEC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

       <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>exec.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;EXEC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

       <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>exec.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

@@ -98,6 +52,4 @@
     <ClCompile Include="exec.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/fishlim/Makefile.am b/plugins/fishlim/Makefile.am
index 255ea0c3..df541396 100644
--- a/plugins/fishlim/Makefile.am
+++ b/plugins/fishlim/Makefile.am
@@ -3,7 +3,7 @@ EXTRA_DIST = INSTALL LICENSE
 libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = fishlim.la
-fishlim_la_SOURCES = fish.c irc.c keystore.c misc.c plugin_hexchat.c
-fishlim_la_LDFLAGS = -avoid-version -module 
-fishlim_la_LIBADD = 
-AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+fishlim_la_SOURCES = fish.c irc.c keystore.c plugin_hexchat.c
+fishlim_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+fishlim_la_LIBADD = $(GLIB_LIBS) $(OPENSSL_LIBS)
+fishlim_la_CFLAGS = $(GLIB_CFLAGS) $(OPENSSL_CFLAGS) -I$(top_srcdir)/src/common
diff --git a/plugins/fishlim/fish.c b/plugins/fishlim/fish.c
index 93420f23..00ecfbfa 100644
--- a/plugins/fishlim/fish.c
+++ b/plugins/fishlim/fish.c
@@ -39,17 +39,17 @@ static const char fish_base64[64] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDE
 static const signed char fish_unbase64[256] = {
     IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB,IB,IB,
     IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB,IB,IB,
-//      !  "  #  $  %  &  '  (    )  *  +  ,  -  .  /
+/*      !  "  #  $  %  &  '  (    )  *  +  ,  -  .  / */
     IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB, 0, 1,
-//   0  1  2  3  4  5  6  7    8  9  :  ;  <  =  >  ?
+/*   0  1  2  3  4  5  6  7    8  9  :  ;  <  =  >  ? */
      2, 3, 4, 5, 6, 7, 8, 9,  10,11,IB,IB,IB,IB,IB,IB,
-//   @  A  B  C  D  E  F  G    H  I  J  K  L  M  N  O
+/*   @  A  B  C  D  E  F  G    H  I  J  K  L  M  N  O */
     IB,38,39,40,41,42,43,44,  45,46,47,48,49,50,51,52,
-//   P  Q  R  S  T  U  V  W    X  Y  Z  [  \  ]  ^  _
+/*   P  Q  R  S  T  U  V  W    X  Y  Z  [  \  ]  ^  _*/
     53,54,55,56,57,58,59,60,  61,62,63,IB,IB,IB,IB,IB,
-//   `  a  b  c  d  e  f  g    h  i  j  k  l  m  n  o
+/*   `  a  b  c  d  e  f  g    h  i  j  k  l  m  n  o */
     IB,12,13,14,15,16,17,18,  19,20,21,22,23,24,25,26,
-//   p  q  r  s  t  u  v  w    x  y  z  {  |  }  ~  <del>
+/*   p  q  r  s  t  u  v  w    x  y  z  {  |  }  ~  <del> */
     27,28,29,30,31,32,33,34,  35,36,37,IB,IB,IB,IB,IB,
 };
 
@@ -75,12 +75,11 @@ char *fish_encrypt(const char *key, size_t keylen, const char *message) {
     
     messagelen = strlen(message);
     if (messagelen == 0) return NULL;
-    encrypted = malloc(((messagelen-1)/8)*12 + 12 + 1); // each 8-byte block becomes 12 bytes
+    encrypted = g_malloc(((messagelen - 1) / 8) * 12 + 12 + 1); /* each 8-byte block becomes 12 bytes */
     end = encrypted;
-    if (!encrypted) return NULL;
      
     while (*message) {
-        // Read 8 bytes (a Blowfish block)
+        /* Read 8 bytes (a Blowfish block) */
         BF_LONG binary[2] = { 0, 0 };
         unsigned char c;
         for (i = 0; i < 8; i++) {
@@ -90,10 +89,10 @@ char *fish_encrypt(const char *key, size_t keylen, const char *message) {
         }
         message += 8;
         
-        // Encrypt block
+        /* Encrypt block */
         BF_encrypt(binary, &bfkey);
         
-        // Emit FiSH-BASE64
+        /* Emit FiSH-BASE64 */
         bit = 0;
         word = 1;
         for (j = 0; j < 12; j++) {
@@ -106,7 +105,7 @@ char *fish_encrypt(const char *key, size_t keylen, const char *message) {
             }
         }
         
-        // Stop if a null terminator was found
+        /* Stop if a null terminator was found */
         if (c == '\0') break;
     }
     *end = '\0';
@@ -124,12 +123,11 @@ char *fish_decrypt(const char *key, size_t keylen, const char *data) {
     unsigned char d;
     BF_set_key(&bfkey, keylen, (const unsigned char*)key);
     
-    decrypted = malloc(strlen(data)+1);
+    decrypted = g_malloc(strlen(data) + 1);
     end = decrypted;
-    if (!decrypted) return NULL;
     
     while (*data) {
-        // Convert from FiSH-BASE64
+        /* Convert from FiSH-BASE64 */
         BF_LONG binary[2] = { 0, 0 };
         bit = 0;
         word = 1;
@@ -144,10 +142,10 @@ char *fish_decrypt(const char *key, size_t keylen, const char *data) {
             }
         }
         
-        // Decrypt block
+        /* Decrypt block */
         BF_decrypt(binary, &bfkey);
         
-        // Copy to buffer
+        /* Copy to buffer */
         GET_BYTES(end, binary[0]);
         GET_BYTES(end, binary[1]);
     }
@@ -165,14 +163,14 @@ char *fish_encrypt_for_nick(const char *nick, const char *data) {
     char *key;
     char *encrypted;
 
-    // Look for key
+    /* Look for key */
     key = keystore_get_key(nick);
     if (!key) return NULL;
     
-    // Encrypt
+    /* Encrypt */
     encrypted = fish_encrypt(key, strlen(key), data);
     
-    free(key);
+    g_free(key);
     return encrypted;
 }
 
@@ -183,14 +181,14 @@ char *fish_encrypt_for_nick(const char *nick, const char *data) {
 char *fish_decrypt_from_nick(const char *nick, const char *data) {
     char *key;
     char *decrypted;
-    // Look for key
+    /* Look for key */
     key = keystore_get_key(nick);
     if (!key) return NULL;
     
-    // Decrypt
+    /* Decrypt */
     decrypted = fish_decrypt(key, strlen(key), data);
     
-    free(key);
+    g_free(key);
     return decrypted;
 }
 
diff --git a/plugins/fishlim/fish.h b/plugins/fishlim/fish.h
index db471326..238f52e7 100644
--- a/plugins/fishlim/fish.h
+++ b/plugins/fishlim/fish.h
@@ -25,9 +25,10 @@
 #ifndef FISH_H
 #define FISH_H
 
-#include <stdbool.h>
 #include <stddef.h>
 
+#include <glib.h>
+
 char *fish_encrypt(const char *key, size_t keylen, const char *message);
 char *fish_decrypt(const char *key, size_t keylen, const char *data);
 char *fish_encrypt_for_nick(const char *nick, const char *data);
diff --git a/plugins/fishlim/fishlim.vcxproj b/plugins/fishlim/fishlim.vcxproj
index f1eb95ba..25492a82 100644
--- a/plugins/fishlim/fishlim.vcxproj
+++ b/plugins/fishlim/fishlim.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>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,57 +20,19 @@
     <RootNamespace>fishlim</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</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>

-    <TargetName>hcfishlim</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcfishlim</TargetName>

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

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

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>fishlim.def</ModuleDefinitionFile>

       <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

@@ -77,19 +40,10 @@
   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>fishlim.def</ModuleDefinitionFile>

       <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

@@ -103,17 +57,13 @@
     <ClInclude Include="fish.h" />

     <ClInclude Include="irc.h" />

     <ClInclude Include="keystore.h" />

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

     <ClInclude Include="plugin_hexchat.h" />

   </ItemGroup>

   <ItemGroup>

     <ClCompile Include="fish.c" />

     <ClCompile Include="irc.c" />

     <ClCompile Include="keystore.c" />

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

     <ClCompile Include="plugin_hexchat.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/fishlim/fishlim.vcxproj.filters b/plugins/fishlim/fishlim.vcxproj.filters
index 7c13733b..d8fbf454 100644
--- a/plugins/fishlim/fishlim.vcxproj.filters
+++ b/plugins/fishlim/fishlim.vcxproj.filters
@@ -32,9 +32,6 @@
     <ClInclude Include="keystore.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="misc.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

     <ClInclude Include="plugin_hexchat.h">

       <Filter>Header Files</Filter>

     </ClInclude>

@@ -49,9 +46,6 @@
     <ClCompile Include="keystore.c">

       <Filter>Source Files</Filter>

     </ClCompile>

-    <ClCompile Include="misc.c">

-      <Filter>Source Files</Filter>

-    </ClCompile>

     <ClCompile Include="plugin_hexchat.c">

       <Filter>Source Files</Filter>

     </ClCompile>

diff --git a/plugins/fishlim/irc.c b/plugins/fishlim/irc.c
index 3586921b..deba545b 100644
--- a/plugins/fishlim/irc.c
+++ b/plugins/fishlim/irc.c
@@ -22,8 +22,9 @@
 
 */
 
-#include <stdlib.h>
-#include <string.h>
+#include "config.h"
+
+#include <glib.h>
 #include "irc.h"
 
 /**
@@ -31,26 +32,26 @@
  * at spaces. The prefix and command is extracted from the message, and
  * parameters_offset is set to the index of the first parameter.
  */
-bool irc_parse_message(const char *words[],
+gboolean irc_parse_message(const char *words[],
                        const char **prefix, const char **command,
                        size_t *parameters_offset) {
     size_t w = 1;
     if (prefix) *prefix = NULL;
     if (command) *command = NULL;
     
-    // See if the message starts with a prefix (sender user)
+    /* See if the message starts with a prefix (sender user) */
     if (words[w][0] == ':') {
         if (prefix) *prefix = &words[w][1];
         w++;
     }
     
-    // Check command
-    if (words[w][0] == '\0') return false;
+    /* Check command */
+    if (words[w][0] == '\0') return FALSE;
     if (command) *command = words[w];
     w++;
     
     *parameters_offset = w;
-    return true;
+    return TRUE;
 }
 
 
@@ -65,48 +66,15 @@ bool irc_parse_message(const char *words[],
  */
 char *irc_prefix_get_nick(const char *prefix) {
     const char *end;
-    char *nick;
     size_t length;
     
     if (!prefix) return NULL;
     
-    // Find end of nick
+    /* Find end of nick */
     end = prefix;
     while (*end != '\0' && *end != '!' && *end != '@') end++;
     
-    // Allocate string
+    /* Allocate string */
     length = end - prefix;
-    nick = malloc(length+1);
-    if (!nick) return NULL;
-    
-    // Copy to string
-    memcpy(nick, prefix, length);
-    nick[length] = '\0';
-    return nick;
-}
-
-
-/**
- * Compares two nick names. Return 0 if equal. Otherwise the return value is
- * less than zero if a is less than b or greater than zero if a is greater
- * than b.
- */
-int irc_nick_cmp(const char *a, const char *b) {
-    char ac;
-    char bc;
-    char diff;
-    for (;;) {
-        ac = *(a++);
-        bc = *(b++);
-        
-        // Change into IRC uppercase (see RFC 2812 section 2.2)
-        if (ac >= 'a' && ac <= '~') ac &= ~0x20;
-        if (bc >= 'a' && bc <= '~') bc &= ~0x20;
-        
-        diff = ac - bc;
-        if (diff) return diff;
-        if (!ac) return 0;
-    }
+    return g_strndup (prefix, length);
 }
-
-
diff --git a/plugins/fishlim/irc.h b/plugins/fishlim/irc.h
index 87317130..c5649233 100644
--- a/plugins/fishlim/irc.h
+++ b/plugins/fishlim/irc.h
@@ -25,14 +25,13 @@
 #ifndef IRC_H
 #define IRC_H
 
-#include <stdbool.h>
 #include <stddef.h>
+#include <glib.h>
 
-bool irc_parse_message(const char *words[],
+gboolean irc_parse_message(const char *words[],
                        const char **prefix, const char **command,
                        size_t *parameters_offset);
 char *irc_prefix_get_nick(const char *prefix);
-int irc_nick_cmp(const char *a, const char *b);
 
 #endif
 
diff --git a/plugins/fishlim/keystore.c b/plugins/fishlim/keystore.c
index 9f1c446e..84373996 100644
--- a/plugins/fishlim/keystore.c
+++ b/plugins/fishlim/keystore.c
@@ -22,12 +22,13 @@
 
 */
 
+#include "config.h"
+
 #include <glib.h>
 #include <stdlib.h>
 #include <string.h>
 #include "irc.h"
 #include "fish.h"
-#include "misc.h"
 #include "keystore.h"
 #include "plugin_hexchat.h"
 
@@ -57,7 +58,7 @@ static GKeyFile *getConfigFile() {
 static const char *get_keystore_password() {
     return (keystore_password != NULL ?
         keystore_password :
-        // Silly default value...
+        /* Silly default value... */
         "blowinikey");
 }
 
@@ -87,17 +88,17 @@ static gchar *get_nick_value(GKeyFile *keyfile, const char *nick, const char *it
  * Extracts a key from the key store file.
  */
 char *keystore_get_key(const char *nick) {
-    // Get the key
+    /* Get the key */
     GKeyFile *keyfile = getConfigFile();
     gchar *value = get_nick_value(keyfile, nick, "key");
     g_key_file_free(keyfile);
     if (!value) return NULL;
     
     if (strncmp(value, "+OK ", 4) != 0) {
-        // Key is stored in plaintext
-        return import_glib_string(value);
+        /* Key is stored in plaintext */
+        return value;
     } else {
-        // Key is encrypted
+        /* Key is encrypted */
         const char *encrypted = value+4;
         const char *password = get_keystore_password();
         char *decrypted = fish_decrypt(password, strlen(password), encrypted);
@@ -109,10 +110,10 @@ char *keystore_get_key(const char *nick) {
 /**
  * Deletes a nick and the associated key in the key store file.
  */
-static bool delete_nick(GKeyFile *keyfile, const char *nick) {
+static gboolean delete_nick(GKeyFile *keyfile, const char *nick) {
     gchar **group;
     gchar **groups = g_key_file_get_groups(keyfile, NULL);
-    bool ok = false;
+    gboolean ok = FALSE;
     
     for (group = groups; *group != NULL; group++) {
         if (!irc_nick_cmp(*group, nick)) {
@@ -125,58 +126,77 @@ static bool delete_nick(GKeyFile *keyfile, const char *nick) {
     return ok;
 }
 
+#if !GLIB_CHECK_VERSION(2,40,0)
 /**
  * Writes the key store file to disk.
  */
-static bool save_keystore(GKeyFile *keyfile) {
-    char *filename;
-    bool ok;
-    // Serialize
+static gboolean keyfile_save_to_file (GKeyFile *keyfile, char *filename) {
+    gboolean ok;
+
+    /* Serialize */
     gsize file_length;
     gchar *file_data = g_key_file_to_data(keyfile, &file_length, NULL);
-    if (!file_data) return false;
-    
-    // Write to file
-    filename = get_config_filename();
-    ok = g_file_set_contents(filename, file_data, file_length, NULL);
-    g_free(filename);
+    if (!file_data)
+        return FALSE;
+
+    /* Write to file */
+    ok = g_file_set_contents (filename, file_data, file_length, NULL);
     g_free(file_data);
     return ok;
 }
+#endif
+
+/**
+ * Writes the key store file to disk.
+ */
+static gboolean save_keystore(GKeyFile *keyfile) {
+    char *filename;
+    gboolean ok;
+
+    filename = get_config_filename();
+#if !GLIB_CHECK_VERSION(2,40,0)
+    ok = keyfile_save_to_file (keyfile, filename);
+#else
+    ok = g_key_file_save_to_file (keyfile, filename, NULL);
+#endif
+    g_free (filename);
+
+    return ok;
+}
 
 /**
  * Sets a key in the key store file.
  */
-bool keystore_store_key(const char *nick, const char *key) {
+gboolean keystore_store_key(const char *nick, const char *key) {
     const char *password;
     char *encrypted;
     char *wrapped;
-    bool ok = false;
+    gboolean ok = FALSE;
     GKeyFile *keyfile = getConfigFile();
     
-    // Remove old key
+    /* Remove old key */
     delete_nick(keyfile, nick);
     
-    // Add new key
+    /* Add new key */
     password = get_keystore_password();
     if (password) {
-        // Encrypt the password
+        /* Encrypt the password */
         encrypted = fish_encrypt(password, strlen(password), key);
         if (!encrypted) goto end;
         
-        // Prepend "+OK "
+        /* Prepend "+OK " */
         wrapped = g_strconcat("+OK ", encrypted, NULL);
         g_free(encrypted);
         
-        // Store encrypted in file
+        /* Store encrypted in file */
         g_key_file_set_string(keyfile, nick, "key", wrapped);
-        free(wrapped);
+        g_free(wrapped);
     } else {
-        // Store unencrypted in file
+        /* Store unencrypted in file */
         g_key_file_set_string(keyfile, nick, "key", key);
     }
     
-    // Save key store file
+    /* Save key store file */
     ok = save_keystore(keyfile);
     
   end:
@@ -187,23 +207,15 @@ bool keystore_store_key(const char *nick, const char *key) {
 /**
  * Deletes a nick from the key store.
  */
-bool keystore_delete_nick(const char *nick) {
+gboolean keystore_delete_nick(const char *nick) {
     GKeyFile *keyfile = getConfigFile();
     
-    // Delete entry
-    bool ok = delete_nick(keyfile, nick);
+    /* Delete entry */
+    gboolean ok = delete_nick(keyfile, nick);
     
-    // Save
+    /* Save */
     if (ok) save_keystore(keyfile);
     
     g_key_file_free(keyfile);
     return ok;
 }
-
-
-void keystore_secure_free(void *ptr, size_t size) {
-    secure_erase(ptr, size);
-    free(ptr);
-}
-
-
diff --git a/plugins/fishlim/keystore.h b/plugins/fishlim/keystore.h
index a2c33f02..3d90606a 100644
--- a/plugins/fishlim/keystore.h
+++ b/plugins/fishlim/keystore.h
@@ -25,14 +25,13 @@
 #ifndef KEYSTORE_H
 #define KEYSTORE_H
 
-#include <stdbool.h>
 #include <stddef.h>
 
-char *keystore_get_key(const char *nick);
-bool keystore_store_key(const char *nick, const char *key);
-bool keystore_delete_nick(const char *nick);
+#include <glib.h>
 
-void keystore_secure_free(void *ptr, size_t size);
+char *keystore_get_key(const char *nick);
+gboolean keystore_store_key(const char *nick, const char *key);
+gboolean keystore_delete_nick(const char *nick);
 
 #endif
 
diff --git a/plugins/fishlim/misc.c b/plugins/fishlim/misc.c
deleted file mode 100644
index 2b78961d..00000000
--- a/plugins/fishlim/misc.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be included in
-  all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-  THE SOFTWARE.
-
-*/
-
-#include <glib.h>
-#include <stdlib.h>
-#include <string.h>
-#include "misc.h"
-
-
-void secure_erase(void *ptr, size_t size) {
-    // "volatile" prevents this code from being optimized away
-    volatile char* volptr = ptr;
-    while (size--) *volptr++ = 0;
-}
-
-/**
- * Re-allocates a string with the native allocator.
- */
-char *import_glib_string(gchar *gstr) {
-    size_t size;
-    char *native;
-    if (g_mem_is_system_malloc()) return gstr;
-    
-    size = strlen(gstr)+1;
-    native = malloc(size);
-    memcpy(native, gstr, size);
-    
-    secure_erase(gstr, size);
-    g_free(gstr);
-    return native;
-}
-
-
diff --git a/plugins/fishlim/misc.h b/plugins/fishlim/misc.h
deleted file mode 100644
index ee4fc5b8..00000000
--- a/plugins/fishlim/misc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be included in
-  all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-  THE SOFTWARE.
-
-*/
-
-#ifndef MISC_H
-#define MISC_H
-
-void secure_erase(void *ptr, size_t size);
-
-#ifdef __G_LIB_H__
-char *import_glib_string(gchar *gstr);
-#endif
-
-#endif
-
-
diff --git a/plugins/fishlim/plugin_hexchat.c b/plugins/fishlim/plugin_hexchat.c
index f200ea8c..556a2f51 100644
--- a/plugins/fishlim/plugin_hexchat.c
+++ b/plugins/fishlim/plugin_hexchat.c
@@ -22,17 +22,14 @@
 
 */
 
+#include "config.h"
+
 #include <glib.h>
 #include <stdlib.h>
 #include <string.h>
 
-// #pragma GCC visibility push(default)
 #include "hexchat-plugin.h"
 #define HEXCHAT_MAX_WORDS 32
-// #pragma GCC visibility pop
-
-//#define EXPORT __attribute((visibility("default")))
-//#define EXPORT
 
 #include "fish.h"
 #include "keystore.h"
@@ -52,26 +49,18 @@ static hexchat_plugin *ph;
  * Returns the path to the key store file.
  */
 gchar *get_config_filename() {
-    return g_build_filename(hexchat_get_info(ph, "configdir"), "addon_fishlim.conf", NULL);
-}
+    char *filename_fs, *filename_utf8;
 
-/**
- * Appends data to a string. Returns true if there was sufficient memory.
- * Frees *s and returns false if an error occurs.
- */
-static bool append(char **s, size_t *length, const char *data) {
-    size_t datalen = strlen(data);
-    char *extended = realloc(*s, *length + datalen + 1);
-    if (!extended) {
-        free(*s);
-        return false;
-    }
-    memcpy(extended + *length, data, datalen + 1);
-    *s = extended;
-    *length += datalen;
-    return true;
+    filename_utf8 = g_build_filename(hexchat_get_info(ph, "configdir"), "addon_fishlim.conf", NULL);
+    filename_fs = g_filename_from_utf8 (filename_utf8, -1, NULL, NULL, NULL);
+
+    g_free (filename_utf8);
+    return filename_fs;
 }
 
+int irc_nick_cmp(const char *a, const char *b) {
+	return hexchat_nickcmp (ph, a, b);
+}
 
 /*static int handle_debug(char *word[], char *word_eol[], void *userdata) {
     hexchat_printf(ph, "debug incoming: ");
@@ -87,26 +76,26 @@ static bool append(char **s, size_t *length, const char *data) {
  */
 static int handle_outgoing(char *word[], char *word_eol[], void *userdata) {
     const char *own_nick;
-    // Encrypt the message if possible
+    /* Encrypt the message if possible */
     const char *channel = hexchat_get_info(ph, "channel");
     char *encrypted = fish_encrypt_for_nick(channel, word_eol[1]);
     if (!encrypted) return HEXCHAT_EAT_NONE;
     
-    // Display message
+    /* Display message */
     own_nick = hexchat_get_info(ph, "nick");
     hexchat_emit_print(ph, "Your Message", own_nick, word_eol[1], NULL);
     
-    // Send message
+    /* Send message */
     hexchat_commandf(ph, "PRIVMSG %s :+OK %s", channel, encrypted);
     
-    free(encrypted);
+    g_free(encrypted);
     return HEXCHAT_EAT_HEXCHAT;
 }
 
 /**
  * Called when a channel message or private message is received.
  */
-static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
+static int handle_incoming(char *word[], char *word_eol[], hexchat_event_attrs *attrs, void *userdata) {
     const char *prefix;
     const char *command;
     const char *recipient;
@@ -114,20 +103,19 @@ static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
     const char *peice;
     char *sender_nick;
     char *decrypted;
-    char *message;
     size_t w;
     size_t ew;
     size_t uw;
-    size_t length;
     char prefix_char = 0;
+    GString *message;
 
     if (!irc_parse_message((const char **)word, &prefix, &command, &w))
         return HEXCHAT_EAT_NONE;
     
-    // Topic (command 332) has an extra parameter
+    /* Topic (command 332) has an extra parameter */
     if (!strcmp(command, "332")) w++;
     
-    // Look for encrypted data
+    /* Look for encrypted data */
     for (ew = w+1; ew < HEXCHAT_MAX_WORDS-1; ew++) {
         const char *s = (ew == w+1 ? word[ew]+1 : word[ew]);
         if (*s && (s[1] == '+' || s[1] == 'm')) { prefix_char = *(s++); }
@@ -136,61 +124,70 @@ static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
     }
     return HEXCHAT_EAT_NONE;
   has_encrypted_data: ;
-    // Extract sender nick and recipient nick/channel
+    /* Extract sender nick and recipient nick/channel */
     sender_nick = irc_prefix_get_nick(prefix);
     recipient = word[w];
     
-    // Try to decrypt with these (the keys are searched for in the key store)
+    /* Try to decrypt with these (the keys are searched for in the key store) */
     encrypted = word[ew+1];
     decrypted = fish_decrypt_from_nick(recipient, encrypted);
     if (!decrypted) decrypted = fish_decrypt_from_nick(sender_nick, encrypted);
     
-    // Check for error
+    /* Check for error */
     if (!decrypted) goto decrypt_error;
     
-    // Build unecrypted message
-    message = NULL;
-    length = 0;
-    if (!append(&message, &length, "RECV")) goto decrypt_error;
-    
+    /* Build unecrypted message */
+    message = g_string_sized_new (100); /* TODO: more accurate estimation of size */
+    g_string_append (message, "RECV");
+
+    if (attrs->server_time_utc)
+    {
+        GTimeVal tv = { (glong)attrs->server_time_utc, 0 };
+        char *timestamp = g_time_val_to_iso8601 (&tv);
+
+       g_string_append (message, " @time=");
+       g_string_append (message, timestamp);
+       g_free (timestamp);
+    }
+
     for (uw = 1; uw < HEXCHAT_MAX_WORDS; uw++) {
-        if (word[uw][0] != '\0' && !append(&message, &length, " ")) goto decrypt_error;
+        if (word[uw][0] != '\0')
+            g_string_append_c (message, ' ');
         
         if (uw == ew) {
-            // Add the encrypted data
+            /* Add the encrypted data */
             peice = decrypted;
-            uw++; // Skip "OK+"
+            uw++; /* Skip "OK+" */
             
             if (ew == w+1) {
-                // Prefix with colon, which gets stripped out otherwise
-                if (!append(&message, &length, ":")) goto decrypt_error;
+                /* Prefix with colon, which gets stripped out otherwise */
+                g_string_append_c (message, ':');
             }
             
             if (prefix_char) {
-                char prefix_str[2] = { prefix_char, '\0' };
-                if (!append(&message, &length, prefix_str)) goto decrypt_error;
+                g_string_append_c (message, prefix_char);
             }
             
         } else {
-            // Add unencrypted data (for example, a prefix from a bouncer or bot)
+            /* Add unencrypted data (for example, a prefix from a bouncer or bot) */
             peice = word[uw];
         }
-        
-        if (!append(&message, &length, peice)) goto decrypt_error;
+
+        g_string_append (message, peice);
     }
-    free(decrypted);
+    g_free(decrypted);
     
-    // Simulate unencrypted message
-    //hexchat_printf(ph, "simulating: %s\n", message);
-    hexchat_command(ph, message);
-    
-    free(message);
-    free(sender_nick);
+    /* Simulate unencrypted message */
+    /* hexchat_printf(ph, "simulating: %s\n", message->str); */
+    hexchat_command(ph, message->str);
+
+    g_string_free (message, TRUE);
+    g_free(sender_nick);
     return HEXCHAT_EAT_HEXCHAT;
   
   decrypt_error:
-    free(decrypted);
-    free(sender_nick);
+    g_free(decrypted);
+    g_free(sender_nick);
     return HEXCHAT_EAT_NONE;
 }
 
@@ -201,23 +198,23 @@ static int handle_setkey(char *word[], char *word_eol[], void *userdata) {
     const char *nick;
     const char *key;
     
-    // Check syntax
+    /* Check syntax */
     if (*word[2] == '\0') {
         hexchat_printf(ph, "%s\n", usage_setkey);
         return HEXCHAT_EAT_HEXCHAT;
     }
     
     if (*word[3] == '\0') {
-        // /setkey password
+        /* /setkey password */
         nick = hexchat_get_info(ph, "channel");
         key = word_eol[2];
     } else {
-        // /setkey #channel password
+        /* /setkey #channel password */
         nick = word[2];
         key = word_eol[3];
     }
     
-    // Set password
+    /* Set password */
     if (keystore_store_key(nick, key)) {
         hexchat_printf(ph, "Stored key for %s\n", nick);
     } else {
@@ -233,15 +230,15 @@ static int handle_setkey(char *word[], char *word_eol[], void *userdata) {
 static int handle_delkey(char *word[], char *word_eol[], void *userdata) {
     const char *nick;
     
-    // Check syntax
+    /* Check syntax */
     if (*word[2] == '\0' || *word[3] != '\0') {
         hexchat_printf(ph, "%s\n", usage_delkey);
         return HEXCHAT_EAT_HEXCHAT;
     }
     
-    nick = word_eol[2];
+    nick = g_strstrip (word_eol[2]);
     
-    // Delete the given nick from the key store
+    /* Delete the given nick from the key store */
     if (keystore_delete_nick(nick)) {
         hexchat_printf(ph, "Deleted key for %s\n", nick);
     } else {
@@ -282,11 +279,11 @@ int hexchat_plugin_init(hexchat_plugin *plugin_handle,
     
     /* Add handlers */
     hexchat_hook_command(ph, "", HEXCHAT_PRI_NORM, handle_outgoing, NULL, NULL);
-    hexchat_hook_server(ph, "NOTICE", HEXCHAT_PRI_NORM, handle_incoming, NULL);
-    hexchat_hook_server(ph, "PRIVMSG", HEXCHAT_PRI_NORM, handle_incoming, NULL);
-    //hexchat_hook_server(ph, "RAW LINE", HEXCHAT_PRI_NORM, handle_debug, NULL);
-    hexchat_hook_server(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
-    hexchat_hook_server(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    hexchat_hook_server_attrs(ph, "NOTICE", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    hexchat_hook_server_attrs(ph, "PRIVMSG", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    /* hexchat_hook_server(ph, "RAW LINE", HEXCHAT_PRI_NORM, handle_debug, NULL); */
+    hexchat_hook_server_attrs(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    hexchat_hook_server_attrs(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
     
     hexchat_printf(ph, "%s plugin loaded\n", plugin_name);
     /* Return success */
diff --git a/plugins/fishlim/plugin_hexchat.h b/plugins/fishlim/plugin_hexchat.h
index 04a1f4ff..f60522e6 100644
--- a/plugins/fishlim/plugin_hexchat.h
+++ b/plugins/fishlim/plugin_hexchat.h
@@ -26,6 +26,7 @@
 #define PLUGIN_HEXCHAT_H
 
 gchar *get_config_filename();
+int irc_nick_cmp (const char *, const char *);
 
 #endif
 
diff --git a/plugins/fishlim/test.c b/plugins/fishlim/test.c
deleted file mode 100644
index b4dc8d91..00000000
--- a/plugins/fishlim/test.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be included in
-  all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-  THE SOFTWARE.
-
-*/
-
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "fish.h"
-
-// We can't use the HexChat plugin API from here...
-gchar *get_config_filename() {
-    const gchar *homedir = g_get_home_dir();
-    return g_build_filename(homedir, ".config", "hexchat", "blow.ini", NULL);
-}
-
-
-static int decrypt(int nick_count, char *nicks[]) {
-    char encrypted[8192];
-    while (fgets(encrypted, sizeof(encrypted), stdin)) {
-        char *msg;
-        for (int i = 0; i < nick_count; i++) {
-            msg = fish_decrypt_from_nick(nicks[i], encrypted);
-            if (msg) goto success;
-        }
-        fprintf(stderr, "None of the recipients were found in the key store!\n");
-        return 1;
-      success:
-        fprintf(stderr, "Decrypted text >>>%s<<<\n", msg);
-        free(msg);
-    }
-    return 0;
-}
-
-static int encrypt(int nick_count, char *nicks[]) {
-    char message[8192];
-    while (fgets(message, sizeof(message), stdin)) {
-        // Remove newline character
-        char *newline = strchr(message, '\n');
-        if (newline) *newline = '\0';
-        
-        bool error = false;
-        for (int i = 0; i < nick_count; i++) {
-            char *encrypted = fish_encrypt_for_nick(nicks[i], message);
-            if (encrypted) {
-                fprintf(stderr, "Encrypted [%s]:  >>>%s<<<\n", nicks[i], encrypted);
-                free(encrypted);
-            } else {
-                error = true;
-            }
-        }
-        
-        if (error) {
-            fprintf(stderr, "Some of the recipients were't found in the key store!\n");
-            return 1;
-        }
-    }
-    return 0;
-}
-
-int main(int argc, char *argv[]) {
-    if (argc < 2) {
-        fprintf(stderr, "usage: %s [-e] nick...\n", argv[0]);
-        return 2;
-    }
-    
-    if (strcmp(argv[1], "-e") == 0) {
-        return encrypt(argc-2, &argv[2]);
-    } else {
-        return decrypt(argc-1, &argv[1]);
-    }
-}
-
-
diff --git a/plugins/mpcinfo/functions.c b/plugins/mpcinfo/functions.c
index ff2d563e..e5993948 100644
--- a/plugins/mpcinfo/functions.c
+++ b/plugins/mpcinfo/functions.c
@@ -14,54 +14,27 @@
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-/*
-typedef int (*MYPROC)(HWND,HWND,char*,char*,BOOL,BOOL); 
-
-int dllProc(char *name, char *data){
-    HINSTANCE hinstLib; 
-    hinstLib = LoadLibrary("mpcinfo");
-    //MYPROC proc;
-    int res;
-    if (hinstLib != NULL){
-       //proc = ;
-       if ((MYPROC) GetProcAddress(hinstLib, name)!=NULL){
-          res=(MYPROC)(NULL,NULL,data,NULL,TRUE,TRUE);
-       }
-       else{fprintf(stderr,"can't get proc: %s\n",name);res=-2;}
-    }
-    else{fprintf(stderr,"can't access dll\n");return -1;}
-    FreeLibrary(hinstLib);
-    return res;
-}
-*/
+#include <glib.h>
 
-/*
-int dllProc(char *name, char *data)
+char *split(char *text, char separator)
 {
-	static HMODULE lib = NULL;
-	if (!lib)
+	int pos = -1;
+	size_t i;
+	for (i = 0; i < strlen(text); i++)
 	{
-		lib = LoadLibraryA ("mpcinfo");
-		if (!lib)
-		{
-			return FALSE;
+		if (text[i] == separator) {
+			pos = i;
+			i = strlen(text) + 1;
 		}
-		FreeLibrary (lib);
 	}
 
-	return TRUE;
-}
-*/
+	if (pos == -1)
+	{
+		return text;
+	}
 
-char *split(char *text, char seperator){
-     //if (DEBUG==1) putlog("splitting");
-     int i;int pos=-1;
-     for (i=0;i<strlen(text);i++){
-         if (text[i]==seperator){pos=i;i=strlen(text)+1;}
-     }
-     if (pos==-1) return text;
-     text[pos]=0;
-     return &(text[pos+1]);
+	text[pos] = 0;
+	return &(text[pos + 1]);
 }
 
 int endsWith(char *text, char *suffix){
@@ -71,21 +44,32 @@ int endsWith(char *text, char *suffix){
     return 0;
 }
 
-int inStr(char *s1, int sl1, char *s2){
-    //if (DEBUG==1) putlog("checking instr");
-	int i;int j;
-	for(i=0;i<sl1-strlen(s2);i++){
-		for (j=0;j<strlen(s2);j++){
-			if (s1[i+j]!=s2[j]) j=strlen(s2)+2;
+int inStr(char *s1, size_t sl1, char *s2)
+{
+	size_t i;
+	for (i = 0; i < sl1 - strlen(s2); i++)
+	{
+		size_t j;
+		for (j = 0; j < strlen(s2); j++)
+		{
+			if (s1[i + j] != s2[j])
+			{
+				j = strlen(s2) + 2;
+			}
+		}
+
+		if (j == strlen(s2))
+		{
+			return i;
 		}
-		if (j==strlen(s2)) return i;
 	}
+
 	return -1;
 }
 
 static char *subString(char *text, int first, int length, int spcKill){
 //if (DEBUG==1) putlog("creating substring");
-	char *ret=(char*) calloc (length+1,sizeof(char)); //malloc(sizeof(char)*(length+1));
+	char *ret = g_new (char, length + 1);
 	int i;
 	ret[length]=0;
 	for (i=0;i<length;i++){
@@ -107,7 +91,7 @@ static char *substring(char *text, int first, int length){return subString(text,
 
 char *readLine(FILE *f){
      //if (DEBUG==1) putlog("reading line from file");
-     char *buffer=(char*)calloc(1024,sizeof(char)); //malloc(sizeof(char)*1024);
+     char *buffer = g_new (char, 1024);
      int pos=0;
      int cc=0;
      while((cc!=EOF)&&(pos<1024)&&(cc!=10)){
@@ -121,14 +105,19 @@ char *readLine(FILE *f){
      return buffer;
 }
 
-char *toUpper(char *text){
-     //if (DEBUG==1) putlog("converting text to upper case");
-     char *ret=(char*) calloc(strlen(text)+1,sizeof(char));
-     int i;
-     for (i=0;i<strlen(text);i++) ret[i]=toupper(text[i]);
-     ret[strlen(text)]=0;
-     //if (DEBUG==1) putlog("uc done");
-     return ret;
+char *toUpper(char *text)
+{
+	char *ret = (char*) calloc(strlen(text) + 1, sizeof(char));
+
+	size_t i;
+	for (i = 0; i < strlen(text); i++)
+	{
+		ret[i] = toupper(text[i]);
+	}
+
+	ret[strlen(text)] = 0;
+
+	return ret;
 }
 
 static char *str3cat(char *s1, char *s2, char *s3){
diff --git a/plugins/mpcinfo/mp3Info.c b/plugins/mpcinfo/mp3Info.c
index 99718624..1af29e45 100644
--- a/plugins/mpcinfo/mp3Info.c
+++ b/plugins/mpcinfo/mp3Info.c
@@ -75,62 +75,25 @@ static char MODES [][13]={"Stereo","Joint-Stereo","Dual-Channel","Mono"};
 
 int iPow(int x, int y){return (int)(pow((double)x,(double) y));}
 
-int str2int(char *text){
-    //if (DEBUG==1) putlog("converting string to int");
-    int i;
-    int ret=0;
-    for (i=1;i<=strlen(text);i++){
-        if ((text[strlen(text)-i]>57)||(text[strlen(text)-i]<48)){
-           hexchat_printf(ph,"invalid char in string: %i",text[strlen(text)-i]);
-           return 255;
-        }
-        ret+=((int)text[strlen(text)-i]-48)*iPow(10,i-1);
-    }
-    //hexchat_printf(ph, "str2int(%s)=%i",text,ret);
-    //if (DEBUG==1) putlog("int converted");
-    return ret;
-}
-/*
-static int getSize(char *file){
-    //if (DEBUG==1) putlog("reading filesize");
-	struct stat info;
-	if (stat(file,&info)!=0) return -1;
-	return info.st_size;
-}*/
-/*
-int inStr(char *s1, int sl1, char *s2){
-    //if (DEBUG==1) putlog("checking instr");
-	int i;int j;
-	for(i=0;i<sl1-strlen(s2);i++){
-		for (j=0;j<strlen(s2);j++){
-			if (s1[i+j]!=s2[j]) j=strlen(s2)+2;
+int str2int(char *text)
+{
+	int ret = 0;
+
+	size_t i;
+	for (i = 1; i <= strlen(text); i++)
+	{
+		if ((text[strlen(text) - i] > 57) || (text[strlen(text) - i] < 48))
+		{
+			hexchat_printf(ph, "invalid char in string: %i", (int) text[strlen(text) - i]);
+			return 255;
 		}
-		if (j==strlen(s2)) return i;
-	}
-	return -1;
-}
 
-static char *subString(char *text, int first, int length, int spcKill){
-//if (DEBUG==1) putlog("creating substring");
-	char *ret=(char*) calloc (length+1,sizeof(char)); //malloc(sizeof(char)*(length+1));
-	ret[length]=0;int i;
-	for (i=0;i<length;i++){
-		ret[i]=text[i+first];
-		//if (ret[i]==0) ret[i]='0';
+		ret += ((int) text[strlen(text) - i] - 48)*iPow(10, i - 1);
 	}
-	if (spcKill==1){
-	   for (i=length-1;i>=0;i--){
-           if (ret[i]==32) ret[i]=0;
-           else i=-1;
-       }
-    }
-    //if (DEBUG==1) putlog("substring created");
+
 	return ret;
 }
 
-static char *substring(char *text, int first, int length){return subString(text,first,length,0);} //1
-*/
-
 static char *tagExtract(char *tag, int tagLen, char* info){
 //if (DEBUG==1) putlog("extracting tag");
 	int pos, len, i;
@@ -204,23 +167,28 @@ struct tagInfo readID3V1(char *file){
 	return ret;
 }
 
-char *extractID3Genre(char *tag){
-     //if (DEBUG==1) putlog("extracting id3 genre");
-     if (tag[strlen(tag)-1]==')'){
-        tag[strlen(tag)-1]=0;
-        tag=&tag[1];
-        return GENRES[str2int(tag)];
-        //return tag;
-     }
-     else{
-          int i;
-          //hexchat_print(ph, "Using 2 criteria");
-          for (i=0;i<strlen(tag);i++){
-              if (tag[i]==')'){ tag=&tag[i]+1;return tag;}
-          //return tag;
-          }
-     }
-     return "[152] failed";
+char *extractID3Genre(char *tag)
+{
+	if (tag[strlen(tag) - 1] == ')')
+	{
+		tag[strlen(tag) - 1] = 0;
+		tag = &tag[1];
+		return GENRES[str2int(tag)];
+	}
+	else
+	{
+		size_t i;
+		for (i = 0; i < strlen(tag); i++)
+		{
+			if (tag[i] == ')')
+			{
+				tag = &tag[i] + 1;
+				return tag;
+			}
+		}
+	}
+
+	return "[152] failed";
 }
 
 struct tagInfo readID3V2(char *file){
diff --git a/plugins/mpcinfo/mpcInfo.c b/plugins/mpcinfo/mpcInfo.c
index 4ab16642..4ad17689 100644
--- a/plugins/mpcinfo/mpcInfo.c
+++ b/plugins/mpcinfo/mpcInfo.c
@@ -48,12 +48,20 @@ static int mpc_tell(char *word[], char *word_eol[], void *userdata){
 	   HWND hwnd = FindWindow("MediaPlayerClassicW",NULL);
        if (hwnd==0) {hexchat_print(ph, randomLine(notRunTheme));return HEXCHAT_EAT_ALL;}
        
-       tTitle=(char*)malloc(sizeof(char)*1024);
+       tTitle = g_new(char, 1024);
        GetWindowText(hwnd, tTitle, 1024);
-       zero=strstr(tTitle," - Media Player Classic");
-       if (zero!=NULL) zero[0]=0;
-       else hexchat_print(ph,"pattern not found");
-       
+       zero = strstr (tTitle, " - Media Player Classic");
+	   if (zero != NULL)
+	   {
+		   zero[0] = 0;
+	   }
+	   else
+	   {
+		   g_free(tTitle);
+		   hexchat_print(ph, "pattern not found");
+		   return HEXCHAT_EAT_ALL;
+	   }
+
        if ((tTitle[1]==':')&&(tTitle[2]=='\\')){
           //hexchat_print(ph,"seams to be full path");
           if (endsWith(tTitle,".mp3")==1){
@@ -82,7 +90,8 @@ static int mpc_tell(char *word[], char *word_eol[], void *userdata){
                 //mp3Line=intReplace(mp3Line,"%perc",perc);
                 //mp3Line=replace(mp3Line,"%plTitle",title);
                 mp3Line=replace(mp3Line,"%file",tTitle);
-                hexchat_command(ph, mp3Line);
+				g_free(tTitle);
+				hexchat_command(ph, mp3Line);
                 return HEXCHAT_EAT_ALL;
              }
           }
@@ -111,14 +120,16 @@ static int mpc_tell(char *word[], char *word_eol[], void *userdata){
                 //oggLine=intReplace(oggLine,"%perc",perc);
                 //oggLine=replace(oggLine,"%plTitle",title);
                 oggLine=replace(oggLine,"%file",tTitle);
-                hexchat_command(ph, oggLine);
+				g_free(tTitle);
+				hexchat_command(ph, oggLine);
                 return HEXCHAT_EAT_ALL;
              }
           }
        }
        line=randomLine(titleTheme);
        line=replace(line,"%title", tTitle);
-       hexchat_command(ph,line); 
+	   g_free(tTitle);
+	   hexchat_command(ph, line);
        return HEXCHAT_EAT_ALL;
 }
 
diff --git a/plugins/mpcinfo/mpcinfo.vcxproj b/plugins/mpcinfo/mpcinfo.vcxproj
index f69e8968..3c4b3e7d 100644
--- a/plugins/mpcinfo/mpcinfo.vcxproj
+++ b/plugins/mpcinfo/mpcinfo.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>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,75 +20,32 @@
     <RootNamespace>mpcinfo</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</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>

-    <TargetName>hcmpcinfo</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcmpcinfo</TargetName>

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

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

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MPCINFO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>..\..\src\common;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>mpcinfo.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;MPCINFO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>..\..\src\common;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>mpcinfo.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

@@ -98,6 +56,4 @@
     <ClCompile Include="mpcInfo.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/mpcinfo/oggInfo.c b/plugins/mpcinfo/oggInfo.c
index 59d84791..e1191649 100644
--- a/plugins/mpcinfo/oggInfo.c
+++ b/plugins/mpcinfo/oggInfo.c
@@ -25,14 +25,18 @@ static int getOggInt(char *buff, int beg, int bytes){
 	return ret;
 }
 
-static char *upperStr(char *text){
-//if (DEBUG==1) putlog("converting text to uc");
-    //printf("upperStr(%s)\n",text);
-	int i;
-	char *ret=(char*) malloc(sizeof(char)*(strlen(text)+1));
-	ret[strlen(text)]=0;
-	for (i=0;i<strlen(text);i++) ret[i]=toupper(text[i]);
-	//printf("Result: %s\n",ret);
+static char *upperStr(char *text)
+{
+	char *ret = (char*) malloc(sizeof(char)*(strlen(text) + 1));
+
+	size_t i;
+	for (i = 0; i < strlen(text); i++)
+	{
+		ret[i] = toupper(text[i]);
+	}
+
+	ret[strlen(text)] = 0;
+
 	return ret;
 }
 
diff --git a/plugins/mpcinfo/theme.c b/plugins/mpcinfo/theme.c
index 3f98a59c..3d8a7a0e 100644
--- a/plugins/mpcinfo/theme.c
+++ b/plugins/mpcinfo/theme.c
@@ -49,24 +49,32 @@ void printThemes(){
      hexchat_printf(ph,"\nTitle-Theme:\n");printTheme(titleTheme);
 }
 
-void cbFix(char *line){
-     //if (DEBUG==1) putlog("cbfix");
-     int i, j;
-     for (i=0;i<strlen(line);i++){
-         if (line[i]=='%'){
-            if ((line[i+1]=='C')||(line[i+1]=='B')||(line[i+1]=='U')||(line[i+1]=='O')||(line[i+1]=='R')){
-               if(line[i+1]=='C') line[i]=3;
-               if(line[i+1]=='B') line[i]=2;
-               if(line[i+1]=='U') line[i]=37;
-               if(line[i+1]=='O') line[i]=17;
-               if(line[i+1]=='R') line[i]=26;
-
-               for (j=i+1;j<strlen(line)-1;j++) line[j]=line[j+1];
-               line[strlen(line)-1]=0;
-            }
-         }
-     }
-     //if (DEBUG==1) putlog("cbfix done");
+void cbFix(char *line)
+{
+	size_t i;
+	for (i = 0; i < strlen(line); i++)
+	{
+		size_t j;
+
+		if (line[i] == '%')
+		{
+			if ((line[i + 1] == 'C') || (line[i + 1] == 'B') || (line[i + 1] == 'U') || (line[i + 1] == 'O') || (line[i + 1] == 'R'))
+			{
+				if (line[i + 1] == 'C') line[i] = 3;
+				if (line[i + 1] == 'B') line[i] = 2;
+				if (line[i + 1] == 'U') line[i] = 37;
+				if (line[i + 1] == 'O') line[i] = 17;
+				if (line[i + 1] == 'R') line[i] = 26;
+
+				for (j = i + 1; j < strlen(line) - 1; j++)
+				{
+					line[j] = line[j + 1];
+				}
+
+				line[strlen(line) - 1] = 0;
+			}
+		}
+	}
 }
 
 struct theme themeAdd(struct theme data, char *info){
diff --git a/plugins/perl/Makefile.am b/plugins/perl/Makefile.am
index 79621549..83239672 100644
--- a/plugins/perl/Makefile.am
+++ b/plugins/perl/Makefile.am
@@ -6,12 +6,13 @@ libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = perl.la
 perl_la_SOURCES = perl.c
-perl_la_LDFLAGS = -avoid-version -module 
-perl_la_LIBADD = $(PERL_LDFLAGS)
+perl_la_LDFLAGS = $(PERL_LDFLAGS) $(PLUGIN_LDFLAGS) -module
+perl_la_LIBADD = $(GLIB_LIBS)
+perl_la_CFLAGS = $(PERL_CFLAGS) $(GLIB_CFLAGS) -I$(top_srcdir)/src/common
+
 BUILT_SOURCES = hexchat.pm.h irc.pm.h
-#CFLAGS = @CFLAGS@ -Wno-unused
-AM_CPPFLAGS = $(PERL_CFLAGS) $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
-CLEANFILES = hexchat.pm.h irc.pm.h
+CLEANFILES = $(BUILT_SOURCES)
+
 hexchat.pm.h irc.pm.h: lib/HexChat.pm lib/Xchat.pm lib/HexChat/Embed.pm \
 	lib/HexChat/List/Network.pm lib/HexChat/List/Network/Entry.pm \
 	lib/HexChat/List/Network/AutoJoin.pm lib/IRC.pm
diff --git a/plugins/perl/perl.c b/plugins/perl/perl.c
index 74333516..b954fb0b 100644
--- a/plugins/perl/perl.c
+++ b/plugins/perl/perl.c
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -31,8 +33,9 @@
 #include <dirent.h>
 #endif
 
+#include <glib.h>
+
 #undef PACKAGE
-#include "../../config.h"
 
 #include "hexchat-plugin.h"
 
@@ -75,37 +78,26 @@ thread_mbox (char *str)
 static void
 perl_auto_load_from_path (const char *path)
 {
-	WIN32_FIND_DATA find_data;
-	HANDLE find_handle;
-	char *search_path;
-	int path_len = strlen (path);
-
-	/* +6 for \*.pl and \0 */
-	search_path = malloc(path_len + 6);
-	sprintf (search_path, "%s\\*.pl", path);
-
-	find_handle = FindFirstFile (search_path, &find_data);
+	char *search_path = g_build_filename (path, "*.pl", NULL);
+	WIN32_FIND_DATAA find_data;
+	HANDLE find_handle = FindFirstFileA (search_path, &find_data);
 
 	if (find_handle != INVALID_HANDLE_VALUE)
 	{
 		do
 		{
-			if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
-				||find_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
+			if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 && (find_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0)
 			{
-				char *full_path =
-					malloc (path_len + strlen (find_data.cFileName) + 2);
-				sprintf (full_path, "%s\\%s", path, find_data.cFileName);
-
+				char *full_path = g_build_filename (path, find_data.cFileName, NULL);
 				perl_load_file (full_path);
-				free (full_path);
+				g_free (full_path);
 			}
 		}
-		while (FindNextFile (find_handle, &find_data) != 0);
+		while (FindNextFileA (find_handle, &find_data) != 0);
 		FindClose (find_handle);
 	}
 
-	free (search_path);
+	g_free (search_path);
 }
 #else
 static void
@@ -115,14 +107,16 @@ perl_auto_load_from_path (const char *path)
 	struct dirent *ent;
 
 	dir = opendir (path);
-	if (dir) {
-		while ((ent = readdir (dir))) {
+	if (dir)
+	{
+		while ((ent = readdir (dir)))
+		{
 			int len = strlen (ent->d_name);
-			if (len > 3 && strcasecmp (".pl", ent->d_name + len - 3) == 0) {
-				char *file = malloc (len + strlen (path) + 2);
-				sprintf (file, "%s/%s", path, ent->d_name);
+			if (len > 3 && strcasecmp (".pl", ent->d_name + len - 3) == 0)
+			{
+				char *file = g_build_filename (path, ent->d_name, NULL);
 				perl_load_file (file);
-				free (file);
+				g_free (file);
 			}
 		}
 		closedir (dir);
@@ -145,31 +139,10 @@ perl_auto_load (void *unused)
 
 	/* don't pollute the filesystem with script files, this only causes misuse of the folders
 	 * only use ~/.config/hexchat/addons/ and %APPDATA%\HexChat\addons */
-#if 0
-	/* autoload from ~/.config/hexchat/ or %APPDATA%\HexChat\ on win32 */
-	perl_auto_load_from_path (xdir);
-#endif
-
-	sub_dir = malloc (strlen (xdir) + 8);
-	strcpy (sub_dir, xdir);
-	strcat (sub_dir, "/addons");
+	sub_dir = g_build_filename (xdir, "addons", NULL);
 	perl_auto_load_from_path (sub_dir);
-	free (sub_dir);
+	g_free (sub_dir);
 
-#if 0
-#ifdef WIN32
-	/* autoload from  C:\Program Files\HexChat\plugins\ */
-	sub_dir = malloc (1025 + 9);
-	copied = GetModuleFileName( 0, sub_dir, 1024 );
-	sub_dir[copied] = '\0';
-	slash = strrchr( sub_dir, '\\' );
-	if( slash != NULL ) {
-		*slash = '\0';
-	}
-	perl_auto_load_from_path ( strncat (sub_dir, "\\plugins", 9));
-	free (sub_dir);
-#endif
-#endif
 	return 0;
 }
 
@@ -288,7 +261,19 @@ list_item_to_sv ( hexchat_list *list, const char *const *fields )
 			field_value = newSVuv (hexchat_list_int (ph, list, field_name));
 			break;
 		case 't':
-			field_value = newSVnv (hexchat_list_time (ph, list, field_name));
+			/* From perldoc for Perl's own timelocal() and timegm():
+			 * <quote>
+			 * On perl versions older than 5.12.0, the range of dates that can be actually be handled depends on the size of time_t (usually a signed integer) on the given platform.
+			 * As of version 5.12.0, perl has stopped using the underlying time library of the operating system it's running on and has its own implementation of those routines with a
+			 * safe range of at least +/ 2**52 (about 142 million years).
+			 * </quote>
+			 *
+			 * This is further confirmed from looking at the source for Time::Local - it's a Perl module and the implementations of timelocal() and timegm() use simple addition and
+			 * subtraction of numbers. Perl automatically promotes numbers from int32_t (IV) to uint32_t (UV) to 64-bit IEEE754 double (NV) as required.
+			 *
+			 * This means that using a double (NV) for our own time_t suffers from the same assumptions that Perl's own functions do.
+			 */
+			field_value = newSVnv ((const NV) hexchat_list_time (ph, list, field_name));
 			break;
 		default:
 			field_value = &PL_sv_undef;
@@ -372,7 +357,7 @@ fd_cb (int fd, int flags, void *userdata)
 				if (data->userdata) {
 					SvREFCNT_dec (data->userdata);
 				}
-				free (data);
+				g_free (data);
 			}
 		}
 
@@ -736,7 +721,7 @@ XS (XS_HexChat_send_modes)
 		if (SvROK (ST (0))) {
 			p_targets = (AV*) SvRV (ST (0));
 			target_count = av_len (p_targets) + 1;
-			targets = malloc (target_count * sizeof (char *));
+			targets = g_new (const char *, target_count);
 			for (i = 0; i < target_count; i++ ) {
 				elem = av_fetch (p_targets, i, 0);
 
@@ -747,13 +732,13 @@ XS (XS_HexChat_send_modes)
 				}
 			}
 		} else{
-			targets = malloc (sizeof (char *));
+			targets = g_new (const char *, 1);
 			targets[0] = SvPV_nolen (ST (0));
 			target_count = 1;
 		}
 		
 		if (target_count == 0) {
-			free (targets);
+			g_free ((char**) targets);
 			XSRETURN_EMPTY;
 		}
 
@@ -765,7 +750,7 @@ XS (XS_HexChat_send_modes)
 		}
 
 		hexchat_send_modes (ph, targets, target_count, modes_per_line, sign, mode);
-		free (targets);
+		g_free ((char**) targets);
 	}
 }
 static
@@ -883,11 +868,7 @@ XS (XS_HexChat_hook_server)
 		userdata = ST (3);
 		package = ST (4);
 		data = NULL;
-		data = malloc (sizeof (HookData));
-		if (data == NULL) {
-			XSRETURN_UNDEF;
-		}
-
+		data = g_new (HookData, 1);
 		data->callback = newSVsv (callback);
 		data->userdata = newSVsv (userdata);
 		data->depth = 0;
@@ -932,11 +913,7 @@ XS (XS_HexChat_hook_command)
 		package = ST (5);
 		data = NULL;
 
-		data = malloc (sizeof (HookData));
-		if (data == NULL) {
-			XSRETURN_UNDEF;
-		}
-
+		data = g_new (HookData, 1);
 		data->callback = newSVsv (callback);
 		data->userdata = newSVsv (userdata);
 		data->depth = 0;
@@ -972,11 +949,7 @@ XS (XS_HexChat_hook_print)
 		userdata = ST (3);
 		package = ST (4);
 
-		data = malloc (sizeof (HookData));
-		if (data == NULL) {
-			XSRETURN_UNDEF;
-		}
-
+		data = g_new (HookData, 1);
 		data->callback = newSVsv (callback);
 		data->userdata = newSVsv (userdata);
 		data->depth = 0;
@@ -1010,11 +983,7 @@ XS (XS_HexChat_hook_timer)
 		userdata = ST (2);
 		package = ST (3);
 
-		data = malloc (sizeof (HookData));
-		if (data == NULL) {
-			XSRETURN_UNDEF;
-		}
-
+		data = g_new (HookData, 1);
 		data->callback = newSVsv (callback);
 		data->userdata = newSVsv (userdata);
 		data->ctx = hexchat_get_context (ph);
@@ -1064,11 +1033,7 @@ XS (XS_HexChat_hook_fd)
 		}
 #endif
 
-		data = malloc (sizeof (HookData));
-		if (data == NULL) {
-			XSRETURN_UNDEF;
-		}
-
+		data = g_new (HookData, 1);
 		data->callback = newSVsv (callback);
 		data->userdata = newSVsv (userdata);
 		data->depth = 0;
@@ -1108,7 +1073,7 @@ XS (XS_HexChat_unhook)
 				SvREFCNT_dec (userdata->package);
 			}
 
-			free (userdata);
+			g_free (userdata);
 		}
 		XSRETURN (retCount);
 	}
diff --git a/plugins/perl/perl.vcxproj b/plugins/perl/perl.vcxproj
index 1a76928d..e9b380ee 100644
--- a/plugins/perl/perl.vcxproj
+++ b/plugins/perl/perl.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>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,66 +20,28 @@
     <RootNamespace>perl520</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</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>

-    <TargetName>$(PerlOutput)</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>$(PerlOutput)</TargetName>

-    <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>

+    <TargetName>hcperl</TargetName>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PERL520_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(PerlPath)\lib\CORE;$(IntDir);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(IntDir);..\..\src\common;$(HexChatLib);$(PerlPath)\lib\CORE;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <AdditionalDependencies>$(PerlLib).lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>$(IntDir);$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(PerlLib).lib;$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>perl.def</ModuleDefinitionFile>

       <DelayLoadDLLs>$(PerlLib).dll;%(DelayLoadDLLs)</DelayLoadDLLs>

     </Link>

     <PreBuildEvent>

       <Command>"$(GendefPath)\gendef" "$(PerlPath)\bin\$(PerlLib).dll"

 move $(PerlLib).def "$(IntDir)"

-lib /nologo /machine:x86 "/def:$(IntDir)$(PerlLib).def" "/out:$(OutDir)\$(PerlLib).lib"

+lib /nologo /machine:x86 "/def:$(IntDir)$(PerlLib).def" "/out:$(IntDir)\$(PerlLib).lib"

 "$(PerlPath)\bin\perl.exe" generate_header

 move irc.pm.h "$(IntDir)"

 move hexchat.pm.h "$(IntDir)"</Command>

@@ -86,28 +49,19 @@ move hexchat.pm.h "$(IntDir)"</Command>
   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;PERL520_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(PerlPath)\lib\CORE;$(IntDir);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(IntDir);..\..\src\common;$(HexChatLib);$(PerlPath)\lib\CORE;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-      <AdditionalDependencies>$(PerlLib).lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>$(IntDir);$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(PerlLib).lib;$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <ModuleDefinitionFile>perl.def</ModuleDefinitionFile>

       <DelayLoadDLLs>$(PerlLib).dll;%(DelayLoadDLLs)</DelayLoadDLLs>

     </Link>

     <PreBuildEvent>

       <Command>"$(GendefPath)\gendef" "$(PerlPath)\bin\$(PerlLib).dll"

 move $(PerlLib).def "$(IntDir)"

-lib /nologo /machine:x64 "/def:$(IntDir)$(PerlLib).def" "/out:$(OutDir)\$(PerlLib).lib"

+lib /nologo /machine:x64 "/def:$(IntDir)$(PerlLib).def" "/out:$(IntDir)\$(PerlLib).lib"

 "$(PerlPath)\bin\perl.exe" generate_header

 move irc.pm.h "$(IntDir)"

 move hexchat.pm.h "$(IntDir)"</Command>

@@ -120,6 +74,4 @@ move hexchat.pm.h "$(IntDir)"</Command>
     <ClCompile Include="perl.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/plugin-conf.in b/plugins/plugin-conf.in
deleted file mode 100644
index f43f5c53..00000000
--- a/plugins/plugin-conf.in
+++ /dev/null
@@ -1,19 +0,0 @@
-AC_INIT(@PLUGIN@-config.h.in)
-AM_CONFIG_HEADER(@PLUGIN@-config.h)
-AM_INIT_AUTOMAKE(hexchat-@PLUGIN@, @PLUGIN_VERSION@)
-AM_MAINTAINER_MODE
-AM_DISABLE_STATIC
-AM_PROG_LIBTOOL
-
-AC_ARG_WITH(plugin-includes,
-[  --with-plugin-includes  directory containing hexchat-plugin.h],
-	PLUGIN_INCLUDES=$enableval)
-
-AC_SUBST(PLUGIN_INCLUDES)
-
-hexchatlibdir=${libdir}/hexchat
-AC_SUBST(hexchatlibdir)
-
-AC_OUTPUT(
-Makefile
-)
diff --git a/plugins/python/Makefile.am b/plugins/python/Makefile.am
index 259f2a0f..063f2009 100644
--- a/plugins/python/Makefile.am
+++ b/plugins/python/Makefile.am
@@ -1,10 +1,8 @@
-EXTRA_DIST = 
-
 libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = python.la
 python_la_SOURCES = python.c
-python_la_LDFLAGS = -avoid-version -module 
-python_la_LIBADD = $(PY_LIBS)
-AM_CPPFLAGS = $(PY_CFLAGS) $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+python_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+python_la_LIBADD = $(PY_LIBS) $(GLIB_LIBS)
+python_la_CFLAGS = $(PY_CFLAGS) $(GLIB_CFLAGS) -I$(top_srcdir)/src/common
 
diff --git a/plugins/python/python.c b/plugins/python/python.c
index 1904a3e9..1f9c7cc9 100644
--- a/plugins/python/python.c
+++ b/plugins/python/python.c
@@ -51,6 +51,8 @@
  *
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <glib/gstdio.h>
 #include <string.h>
@@ -64,9 +66,9 @@
 #include <dirent.h>
 #endif
 
-#include "../../config.h"
 #include "hexchat-plugin.h"
-#undef _POSIX_C_SOURCE	/* Avoid warning: also in /usr/include/features.h from glib.h */
+#undef _POSIX_C_SOURCE	/* Avoid warnings from /usr/include/features.h */
+#undef _XOPEN_SOURCE
 #include <Python.h>
 #include <structmember.h>
 #include <pythread.h>
@@ -414,6 +416,9 @@ Util_BuildEOLList(char *word[])
 	PyObject *list;
 	int listsize = 31;
 	int i;
+	char *accum = NULL;
+	char *last = NULL;
+
 	/* Find the last valid array member; there may be intermediate NULLs that
 	 * would otherwise cause us to drop some members. */
 	while (listsize > 0 &&
@@ -424,10 +429,9 @@ Util_BuildEOLList(char *word[])
 		PyErr_Print();
 		return NULL;
 	}
-	char *accum = NULL;
-	char *last = NULL;
 	for (i = listsize; i > 0; i--) {
 		char *part = word[i];
+		PyObject *uni_part;
 		if (accum == NULL) {
 			accum = g_strdup (part);
 		} else if (part != NULL && part[0] != 0) {
@@ -443,14 +447,12 @@ Util_BuildEOLList(char *word[])
 				return NULL;
 			}
 		}
-		PyObject *uni_part = PyUnicode_FromString(accum);
+		uni_part = PyUnicode_FromString(accum);
 		PyList_SetItem(list, i - 1, uni_part);
 	}
 
-	if (last)
-		g_free (last);
-	if (accum)
-		g_free (accum);
+	g_free (last);
+	g_free (accum);
 
 	return list;
 }
@@ -800,9 +802,7 @@ Callback_ThreadTimer(void *userdata)
 /* We keep this information global, so we can reset it when the
  * deinit function is called. */
 /* XXX This should be somehow bound to the printing context. */
-static char *xchatout_buffer = NULL;
-static int xchatout_buffer_size = 0;
-static int xchatout_buffer_pos = 0;
+static GString *xchatout_buffer = NULL;
 
 static PyObject *
 XChatOut_New()
@@ -826,76 +826,42 @@ XChatOut_dealloc(PyObject *self)
 static PyObject *
 XChatOut_write(PyObject *self, PyObject *args)
 {
-	int new_buffer_pos, data_size, print_limit, add_space;
+	gboolean add_space;
 	char *data, *pos;
-	if (!PyArg_ParseTuple(args, "s#:write", &data, &data_size))
+
+	if (!PyArg_ParseTuple(args, "s:write", &data))
 		return NULL;
-	if (!data_size) {
-		Py_INCREF(Py_None);
-		return Py_None;
+	if (!data || !*data) {
+		Py_RETURN_NONE;
 	}
 	BEGIN_XCHAT_CALLS(RESTORE_CONTEXT|ALLOW_THREADS);
 	if (((XChatOutObject *)self)->softspace) {
-		add_space = 1;
+		add_space = TRUE;
 		((XChatOutObject *)self)->softspace = 0;
 	} else {
-		add_space = 0;
-	}
-	if (xchatout_buffer_size-xchatout_buffer_pos < data_size+add_space) {
-		char *new_buffer;
-		/* This buffer grows whenever needed, and does not
-		 * shrink. If we ever implement unloading of the
-		 * python interface, we must find some way to free
-		 * this buffer as well. */
-		xchatout_buffer_size += data_size*2+16;
-		new_buffer = g_realloc(xchatout_buffer, xchatout_buffer_size);
-		if (new_buffer == NULL) {
-			hexchat_print(ph, "Not enough memory to print");
-			/* The system is out of resources. Let's help. */
-			g_free(xchatout_buffer);
-			xchatout_buffer = NULL;
-			xchatout_buffer_size = 0;
-			xchatout_buffer_pos = 0;
-			/* Return something valid, since we have
-			 * already warned the user, and he probably
-			 * won't be able to notice this exception. */
-			goto exit;
-		}
-		xchatout_buffer = new_buffer;
-	}
-	memcpy(xchatout_buffer+xchatout_buffer_pos, data, data_size);
-	print_limit = new_buffer_pos = xchatout_buffer_pos+data_size;
-	pos = xchatout_buffer+print_limit;
-	if (add_space && *(pos-1) != '\n') {
-		*pos = ' ';
-		*(pos+1) = 0;
-		new_buffer_pos++;
-	}
-	while (*pos != '\n' && print_limit > xchatout_buffer_pos) {
-		pos--;
-		print_limit--;
-	}
-	if (*pos == '\n') {
-		/* Crop it, inserting the string limiter there. */
-		*pos = 0;
-		hexchat_print(ph, xchatout_buffer);
-		if (print_limit < new_buffer_pos) {
-			/* There's still data to be printed. */
-			print_limit += 1; /* Include the limiter. */
-			xchatout_buffer_pos = new_buffer_pos-print_limit;
-			memmove(xchatout_buffer, xchatout_buffer+print_limit,
-				xchatout_buffer_pos);
-		} else {
-			xchatout_buffer_pos = 0;
-		}
-	} else {
-		xchatout_buffer_pos = new_buffer_pos;
+		add_space = FALSE;
+	}
+
+	g_string_append (xchatout_buffer, data);
+
+	/* If not end of line add space to continue buffer later */
+	if (add_space && xchatout_buffer->str[xchatout_buffer->len - 1] != '\n')
+	{
+		g_string_append_c (xchatout_buffer, ' ');
+	}
+
+	/* If there is an end of line print up to that */
+	if ((pos = strrchr (xchatout_buffer->str, '\n')))
+	{
+		*pos = '\0';
+		hexchat_print (ph, xchatout_buffer->str);
+
+		/* Then remove it from buffer */
+		g_string_erase (xchatout_buffer, 0, pos - xchatout_buffer->str + 1);
 	}
 
-exit:
 	END_XCHAT_CALLS();
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 #define OFF(x) offsetof(XChatOutObject, x)
@@ -1047,8 +1013,7 @@ Context_set(ContextObject *self, PyObject *args)
 {
 	PyObject *plugin = Plugin_GetCurrent();
 	Plugin_SetContext(plugin, self->context);
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1061,8 +1026,7 @@ Context_command(ContextObject *self, PyObject *args)
 	hexchat_set_context(ph, self->context);
 	hexchat_command(ph, text);
 	END_XCHAT_CALLS();
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1075,8 +1039,7 @@ Context_prnt(ContextObject *self, PyObject *args)
 	hexchat_set_context(ph, self->context);
 	hexchat_print(ph, text);
 	END_XCHAT_CALLS();
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1121,8 +1084,7 @@ Context_get_info(ContextObject *self, PyObject *args)
 	info = hexchat_get_info(ph, name);
 	END_XCHAT_CALLS();
 	if (info == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
+		Py_RETURN_NONE;
 	}
 	return PyUnicode_FromString(info);
 }
@@ -1405,11 +1367,7 @@ static Hook *
 Plugin_AddHook(int type, PyObject *plugin, PyObject *callback,
 	       PyObject *userdata, char *name, void *data)
 {
-	Hook *hook = (Hook *) g_malloc(sizeof(Hook));
-	if (hook == NULL) {
-		PyErr_NoMemory();
-		return NULL;
-	}
+	Hook *hook = g_new(Hook, 1);
 	hook->type = type;
 	hook->plugin = plugin;
 	Py_INCREF(callback);
@@ -1463,8 +1421,7 @@ Plugin_RemoveHook(PyObject *plugin, Hook *hook)
 					       hook));
 		Py_DECREF(hook->callback);
 		Py_DECREF(hook->userdata);
-		if (hook->name)
-			g_free(hook->name);
+		g_free(hook->name);
 		g_free(hook);
 	}
 }
@@ -1483,8 +1440,7 @@ Plugin_RemoveAllHooks(PyObject *plugin)
 		}
 		Py_DECREF(hook->callback);
 		Py_DECREF(hook->userdata);
-		if (hook->name)
-			g_free(hook->name);
+		g_free(hook->name);
 		g_free(hook);
 		list = list->next;
 	}
@@ -1713,8 +1669,7 @@ Module_hexchat_command(PyObject *self, PyObject *args)
 	BEGIN_XCHAT_CALLS(RESTORE_CONTEXT|ALLOW_THREADS);
 	hexchat_command(ph, text);
 	END_XCHAT_CALLS();
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1726,8 +1681,7 @@ Module_xchat_prnt(PyObject *self, PyObject *args)
 	BEGIN_XCHAT_CALLS(RESTORE_CONTEXT|ALLOW_THREADS);
 	hexchat_print(ph, text);
 	END_XCHAT_CALLS();
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1770,8 +1724,7 @@ Module_hexchat_get_info(PyObject *self, PyObject *args)
 	info = hexchat_get_info(ph, name);
 	END_XCHAT_CALLS();
 	if (info == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
+		Py_RETURN_NONE;
 	}
 	if (strcmp (name, "gtkwin_ptr") == 0)
 		return PyUnicode_FromFormat("%p", info); /* format as pointer */
@@ -1824,8 +1777,7 @@ Module_hexchat_get_context(PyObject *self, PyObject *args)
 		return NULL;
 	ctxobj = Context_FromContext(Plugin_GetContext(plugin));
 	if (ctxobj == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
+		Py_RETURN_NONE;
 	}
 	return ctxobj;
 }
@@ -1842,8 +1794,7 @@ Module_hexchat_find_context(PyObject *self, PyObject *args, PyObject *kwargs)
 		return NULL;
 	ctxobj = Context_FromServerAndChannel(server, channel);
 	if (ctxobj == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
+		Py_RETURN_NONE;
 	}
 	return ctxobj;
 }
@@ -1889,7 +1840,7 @@ Module_hexchat_pluginpref_get(PyObject *self, PyObject *args)
 	if (!PyArg_ParseTuple(args, "s:get_pluginpref", &var))
 		return NULL;
 		
-	// This will always return numbers as integers.
+	/* This will always return numbers as integers. */
 	BEGIN_XCHAT_CALLS(NONE);
 	result = hexchat_pluginpref_get_str(prefph, var, retstr);
 	END_XCHAT_CALLS();
@@ -2223,8 +2174,7 @@ Module_hexchat_unhook(PyObject *self, PyObject *args)
 		Plugin_RemoveHook(plugin, hook);
 	}	
 
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -2532,11 +2482,8 @@ IInterp_Exec(char *command)
 	}
 	d = PyModule_GetDict(m);
 	len = strlen(command);
-	buffer = (char *) g_malloc(len+2);
-	if (buffer == NULL) {
-		hexchat_print(ph, "Not enough memory for command buffer");
-		goto fail;
-	}
+
+	buffer = g_malloc(len + 2);
 	memcpy(buffer, command, len);
 	buffer[len] = '\n';
 	buffer[len+1] = 0;
@@ -2782,6 +2729,7 @@ hexchat_plugin_init(hexchat_plugin *plugin_handle,
 	Py_Initialize();
 	PySys_SetArgv(1, argv);
 
+	xchatout_buffer = g_string_new (NULL);
 	xchatout = XChatOut_New();
 	if (xchatout == NULL) {
 		hexchat_print(ph, "Can't allocate xchatout object");
@@ -2852,10 +2800,8 @@ hexchat_plugin_deinit()
 	plugin_list = NULL;
 
 	/* Reset xchatout buffer. */
-	g_free(xchatout_buffer);
+	g_string_free (xchatout_buffer, TRUE);
 	xchatout_buffer = NULL;
-	xchatout_buffer_size = 0;
-	xchatout_buffer_pos = 0;
 
 	if (interp_plugin) {
 		Py_DECREF(interp_plugin);
diff --git a/plugins/python/python2.vcxproj b/plugins/python/python2.vcxproj
index 58a9e45e..ecf0df75 100644
--- a/plugins/python/python2.vcxproj
+++ b/plugins/python/python2.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>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,80 +20,33 @@
     <RootNamespace>python2</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</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>

-    <TargetName>$(Python2Output)</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>$(Python2Output)</TargetName>

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

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

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(Glib);$(Python2Path)\include;..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(Glib);$(Python2Path)\include;..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>python.def</ModuleDefinitionFile>

       <AdditionalDependencies>"$(Python2Lib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(OutDir);$(Python2Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(Python2Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(Glib);$(Python2Path)\include;..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(Glib);$(Python2Path)\include;..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>python.def</ModuleDefinitionFile>

       <AdditionalDependencies>"$(Python2Lib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(OutDir);$(Python2Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(Python2Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

@@ -102,6 +56,4 @@
     <ClCompile Include="python.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/python/python3.vcxproj b/plugins/python/python3.vcxproj
index 5f970975..511421e6 100644
--- a/plugins/python/python3.vcxproj
+++ b/plugins/python/python3.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>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,80 +20,33 @@
     <RootNamespace>python3</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</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>

-    <TargetName>$(Python3Output)</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>$(Python3Output)</TargetName>

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

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

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(Glib);$(Python3Path)\include;..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(Glib);$(Python3Path)\include;..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>python.def</ModuleDefinitionFile>

       <AdditionalDependencies>"$(Python3Lib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(OutDir);$(Python3Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(Python3Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(Glib);$(Python3Path)\include;..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>$(Glib);$(Python3Path)\include;..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>python.def</ModuleDefinitionFile>

       <AdditionalDependencies>"$(Python3Lib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(OutDir);$(Python3Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(Python3Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

@@ -102,6 +56,4 @@
     <ClCompile Include="python.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/sysinfo/Makefile.am b/plugins/sysinfo/Makefile.am
index 0b8d7fad..bd44a19d 100644
--- a/plugins/sysinfo/Makefile.am
+++ b/plugins/sysinfo/Makefile.am
@@ -1,7 +1,17 @@
 libdir = $(hexchatlibdir)
 
+sources = sysinfo.c format.c shared/df.c
+
+if PLATFORM_OSX
+sources += osx/backend.m
+else
+sources += unix/backend.c unix/match.c unix/parse.c unix/pci.c
+endif
+
+EXTRA_DIST = osx unix win32 shared format.h sysinfo.h sysinfo-backend.h
+
 lib_LTLIBRARIES = sysinfo.la
-sysinfo_la_SOURCES = hwmon.c match.c parse.c pci.c xsys.c
-sysinfo_la_LDFLAGS = -avoid-version -module
-sysinfo_la_LIBADD = -lpci
-AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+sysinfo_la_SOURCES = $(sources)
+sysinfo_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+sysinfo_la_LIBADD = $(LIBPCI_LIBS) $(GLIB_LIBS)
+AM_CPPFLAGS = $(LIBPCI_CFLAGS) $(GLIB_CFLAGS) -I$(top_srcdir)/src/common -I$(srcdir)/shared
diff --git a/plugins/sysinfo/format.c b/plugins/sysinfo/format.c
new file mode 100644
index 00000000..741c43e2
--- /dev/null
+++ b/plugins/sysinfo/format.c
@@ -0,0 +1,90 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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 <glib.h>
+
+char *
+sysinfo_format_uptime (gint64 uptime)
+{
+	char buffer[128];
+
+	gint64 weeks = uptime / 604800;
+	int days     = (uptime / 86400) % 7;
+	int hours    = (uptime / 3600) % 24;
+	int minutes  = (uptime / 60) % 60;
+	int seconds  = uptime % 60;
+
+	if (weeks != 0)
+	{
+		g_snprintf (buffer, sizeof(buffer), "%" G_GINT64_FORMAT "w %dd %dh %dm %ds", weeks, days, hours, minutes, seconds);
+	}
+	else if (days != 0)
+	{
+		g_snprintf (buffer, sizeof(buffer), "%dd %dh %dm %ds", days, hours, minutes, seconds);
+	}
+	else if (hours != 0)
+	{
+		g_snprintf (buffer, sizeof(buffer), "%dh %dm %ds", hours, minutes, seconds);
+	}
+	else if (minutes != 0)
+	{
+		g_snprintf (buffer, sizeof(buffer), "%dm %ds", minutes, seconds);
+	}
+	else
+	{
+		g_snprintf (buffer, sizeof(buffer), "%ds", seconds);
+	}
+
+	return g_strdup (buffer);
+}
+
+char *
+sysinfo_format_memory (guint64 totalmem, guint64 freemem)
+{
+	char *total_fmt, *free_fmt, *ret;
+
+	total_fmt = g_format_size_full (totalmem, G_FORMAT_SIZE_IEC_UNITS);
+	free_fmt = g_format_size_full (freemem, G_FORMAT_SIZE_IEC_UNITS);
+	ret = g_strdup_printf ("%s Total (%s Free)", total_fmt, free_fmt);
+
+	g_free (total_fmt);
+	g_free (free_fmt);
+	return ret;
+}
+
+char *
+sysinfo_format_disk (guint64 total, guint64 free)
+{
+	char *total_fmt, *free_fmt, *used_fmt, *ret;
+	GFormatSizeFlags format_flags = G_FORMAT_SIZE_DEFAULT;
+
+#ifdef WIN32 /* Windows uses IEC size (with SI format) */
+	format_flags = G_FORMAT_SIZE_IEC_UNITS;
+#endif
+
+	total_fmt = g_format_size_full (total, format_flags);
+	free_fmt = g_format_size_full (free, format_flags);
+	used_fmt = g_format_size_full (total - free, format_flags);
+	ret = g_strdup_printf ("%s / %s (%s Free)", used_fmt, total_fmt, free_fmt);
+
+	g_free (total_fmt);
+	g_free (free_fmt);
+	g_free (used_fmt);
+	return ret;
+}
diff --git a/plugins/sysinfo/xsys.h b/plugins/sysinfo/format.h
index 4daf8545..5fe209be 100644
--- a/plugins/sysinfo/xsys.h
+++ b/plugins/sysinfo/format.h
@@ -1,7 +1,6 @@
 /*
- * xsys.h - X-Sys general parameters header
- * Copyright (C) 2005 Gustavo Zacarias
- * Copyright (C) 2006, 2007 Tony Vroon
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
  *
  * 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
@@ -19,14 +18,11 @@
  */
 
 
-#ifndef _XSYS_H_
-#define _XSYS_H_
+#ifndef FORMAT_H
+#define FORMAT_H
 
-#define bsize 1024
-#define delims ":="
-
-int sysinfo_get_percent ();
-void sysinfo_get_pciids (char *dest);
-void sysinfo_print_error (const char* msg);
+char *sysinfo_format_uptime(gint64 uptime);
+char *sysinfo_format_memory(guint64 totalmem, guint64 freemem);
+char *sysinfo_format_disk(guint64 total, guint64 free);
 
 #endif
diff --git a/plugins/sysinfo/hwmon.c b/plugins/sysinfo/hwmon.c
deleted file mode 100644
index 389244ac..00000000
--- a/plugins/sysinfo/hwmon.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * hwmon.c - Hardware monitoring functions for X-Sys
- * Copyright (C) 2005 Tony Vroon
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include "xsys.h"
-
-int hwmon_chip_present()
-{
-	FILE *fp = fopen("/sys/class/hwmon/hwmon0/device/name", "r");
-	if(fp != NULL) {
-		fclose(fp);
-		return 1;
-	}
-	return 0;
-}
-
-#if 0
-void get_hwmon_chip_name(char *name)
-{
-	char *position, buffer[bsize];
-	FILE *fp = fopen("/sys/class/hwmon/hwmon0/device/name", "r");
-	if(fp != NULL) {
-		if(fgets(buffer, bsize, fp) != NULL) {
-			position = strstr(buffer, "\n");
-                        *(position) = '\0';
-			snprintf(name, sizeof(name), "%s", buffer);
-		}
-		fclose(fp);
-	}
-}
-#endif
-
-void get_hwmon_temp(unsigned int *value, unsigned int *sensor)
-{
-	char buffer[bsize];
-	snprintf(buffer, bsize, "/sys/class/hwmon/hwmon0/device/temp%i_input", *sensor);
-	FILE *fp = fopen(buffer, "r");
-	if(fp != NULL) {
-		if(fgets(buffer, bsize, fp) != NULL)
-			*value = atoi(buffer);
-		fclose(fp);
-	}
-}
diff --git a/plugins/sysinfo/match.c b/plugins/sysinfo/match.c
deleted file mode 100644
index adfbff1b..00000000
--- a/plugins/sysinfo/match.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * match.c - matching functions for X-Sys
- * Copyright (C) 2005, 2006, 2007 Tony Vroon
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include "xsys.h"
-
-float percentage(unsigned long long *free, unsigned long long *total)
-{
-        unsigned long long result = (*free) * (unsigned long long)1000 / (*total);
-        return result / 10.0;
-}
-
-char *pretty_freespace(const char *desc, unsigned long long *free_k, unsigned long long *total_k)
-{
-        char *result, **quantity;
-	double free_space, total_space;
-	free_space = *free_k;
-	total_space = *total_k;
-        result = malloc(bsize * sizeof(char));
-	char *quantities[] = { "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", 0 };
-	if (total_space == 0)
-	{
-		snprintf(result, bsize, "%s: none", desc);
-		return result;
-	}
-        quantity = quantities;
-	while (total_space > 1023 && *(quantity + 1))
-	{
-		quantity++;
-		free_space = free_space / 1024;
-		total_space = total_space / 1024;
-	}
-	if (sysinfo_get_percent () != 0)
-		snprintf(result, bsize, "%s: %.1f%s, %.1f%% free",
-		desc, total_space, *quantity,
-		percentage(free_k, total_k));
-	else
-		snprintf(result, bsize, "%s: %.1f%s/%.1f%s free",
-		desc, free_space, *quantity, total_space, *quantity);
-        return result;
-}
-
-
-void remove_leading_whitespace(char *buffer)
-{
-	char *buffer2 = NULL;
-	int i = 0, j = 0, ews = 0;
-
-	buffer2 = (char*)malloc(strlen(buffer) * sizeof(char));
-	if (buffer2 == NULL)
-		return;
-
-	memset (buffer2, (char)0, strlen(buffer));
-	while (i < strlen(buffer))
-	{
-		/* count tabs, spaces as whitespace. */
-		if (!(buffer[i] == (char)32 || buffer[i] == (char)9) || ews == 1)
-		{
-			ews = 1;
-			buffer2[j] = buffer[i];
-			j++;
-		}
-		i++;
-	}
-	memset (buffer, (char)0, strlen(buffer));
-	strcpy (buffer, buffer2);
-	free (buffer2);
-}
-
-char *decruft_filename(char *buffer)
-{
-	char *match, *match_end;
-
-	while ((match = strstr(buffer, "%20")))
-	{
-		match_end = match + 3;
-		*match++ = ' ';
-		while (*match_end)
-			*match++ = *match_end++;
-		*match = 0;
-	}
-	return buffer;
-}
-
-void find_match_char(char *buffer, char *match, char *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-				position += 1;
-				strcpy(result, position);
-				position = strstr(result, "\n");
-				*(position) = '\0';
-				remove_leading_whitespace(result);
-				}
-			else
-				strcpy(result, "\0");
-		}
-}
-
-void find_match_double(char *buffer, char *match, double *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-                        	position += 1;
-                        	*result = strtod(position, NULL);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void find_match_double_hex(char *buffer, char *match, double *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-				memcpy(position,"0x",2);
-				*result = strtod(position,NULL);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void find_match_int(char *buffer, char *match, unsigned int *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-                        	position += 1;
-                        	*result = atoi(position);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void find_match_ll(char *buffer, char *match, unsigned long long *result)
-{
-	char *position;
-	remove_leading_whitespace(buffer);
-	if(strstr(buffer, match) == strstr(buffer, buffer))
-		{
-			position = strpbrk(buffer, delims);
-			if (position != NULL) {
-		               	position += 1;
-		               	*result = strtoll(position, NULL, 10);
-				}
-			else
-				*result = 0;
-		}
-}
-
-void format_output(const char *arg, char *string, char *format)
-{
-        char *pos1, *pos2, buffer[bsize];
-        pos1 = &format[0];
-        strncpy(buffer, string, bsize);
-        string[0] = '\0';
-
-        while((pos2 = strstr(pos1, "%")) != NULL)
-        {
-                strncat(string, pos1, (size_t)(pos2-pos1));
-                if(*(pos2+1) == '1')
-                        strcat(string, arg);
-                else if(*(pos2+1) == '2')
-                        strcat(string, buffer);
-                else if(*(pos2+1) == 'C' || *(pos2+1) == 'c')
-                        strcat(string, "\003");
-                else if(*(pos2+1) == 'B' || *(pos2+1) == 'b')
-                        strcat(string, "\002");
-                else if(*(pos2+1) == 'R' || *(pos2+1) == 'r')
-                        strcat(string, "\026");
-                else if(*(pos2+1) == 'O' || *(pos2+1) == 'o')
-                        strcat(string, "\017");
-                else if(*(pos2+1) == 'U' || *(pos2+1) == 'u')
-                        strcat(string, "\037");
-                else if(*(pos2+1) == '%')
-                        strcat(string, "%");
-                pos1=pos2+2;
-        }
-
-        strcat(string, pos1);
-}
-
-void flat_format_output(const char *arg, char *string, char *format)
-{
-        char *pos1, *pos2, buffer[bsize];
-        pos1 = &format[0];
-        strncpy(buffer, string, bsize);
-        string[0] = '\0';
-
-        while((pos2 = strstr(pos1, "%")) != NULL)
-        {
-                strncat(string, pos1, (size_t)(pos2-pos1));
-                if(*(pos2+1) == '1')
-                        strcat(string, arg);
-                else if(*(pos2+1) == '2')
-                        strcat(string, buffer);
-                else if(*(pos2+1) == '%')
-                        strcat(string, "%");
-                pos1=pos2+2;
-        }
-
-        strcat(string, pos1);
-}
diff --git a/plugins/sysinfo/osx/backend.m b/plugins/sysinfo/osx/backend.m
new file mode 100644
index 00000000..450a557a
--- /dev/null
+++ b/plugins/sysinfo/osx/backend.m
@@ -0,0 +1,263 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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
+ */
+
+ /*
+	* Some snippets based upon Textual's System Profiler plugin.
+	* https://github.com/Codeux-Software/Textual
+	*/
+
+#import <Cocoa/Cocoa.h>
+
+#include <sys/sysctl.h>
+#include <mach/mach.h>
+#include <mach/mach_host.h>
+#include <mach/host_info.h>
+#include <mach/mach_vm.h>
+
+#include <glib.h>
+
+#include "format.h"
+#include "df.h"
+
+static char *
+get_os (void)
+{
+	NSDictionary *systemversion = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
+	NSString *build = [systemversion objectForKey:@"ProductBuildVersion"];
+	if (!build)
+		return NULL;
+	NSString *version = [systemversion objectForKey:@"ProductUserVisibleVersion"];
+	if (!version)
+	{
+		[build release];
+		return NULL;
+	}
+
+	NSDictionary *profiler = [NSDictionary dictionaryWithContentsOfFile:[@"~/Library/Preferences/com.apple.SystemProfiler.plist" stringByExpandingTildeInPath]];
+	NSDictionary *names = [profiler objectForKey:@"OS Names"];
+	NSString *os_name = nil;
+
+	for (NSString *name in names)
+	{
+		if ([name hasPrefix:build])
+		{
+			os_name = [names objectForKey:name];
+			break;
+		}
+	}
+	[build release];
+
+	if (!os_name)
+	{
+		[version release];
+		return NULL;
+	}
+
+	char *ret = g_strdup_printf ("%s %s", [os_name UTF8String], [version UTF8String]);
+	[version release];
+
+	return ret;
+}
+
+static char *
+get_os_fallback (void)
+{
+	NSProcessInfo *info = [NSProcessInfo processInfo];
+	NSOperatingSystemVersion version = [info operatingSystemVersion];
+
+	return g_strdup_printf ("OS X %ld.%ld.%ld", version.majorVersion, version.minorVersion, version.patchVersion);
+}
+char *
+sysinfo_backend_get_os(void)
+{
+	static char *os_str = NULL;
+	if (!os_str)
+	{
+		os_str = get_os();
+		if (!os_str)
+			os_str = get_os_fallback();
+	}
+	return g_strdup (os_str);
+}
+
+char *
+sysinfo_backend_get_disk(void)
+{
+	gint64 total, free_space;
+
+	if (xs_parse_df (&total, &free_space))
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_disk (total, free_space);
+}
+
+static guint64
+get_free_memory (void)
+{
+	mach_msg_type_number_t infoCount = (sizeof(vm_statistics_data_t) / sizeof(natural_t));
+
+	vm_size_t pagesize;
+	vm_statistics_data_t vm_stat;
+
+	host_page_size(mach_host_self(), &pagesize);
+
+	if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stat, &infoCount) == KERN_SUCCESS)
+		return ((vm_stat.inactive_count + vm_stat.free_count) * pagesize);
+
+	return 0;
+}
+
+char *
+sysinfo_backend_get_memory(void)
+{
+	NSProcessInfo *info = [NSProcessInfo processInfo];
+	guint64 totalmem, freemem;
+
+	totalmem = [info physicalMemory];
+
+	if ((freemem = get_free_memory()) == 0)
+		return NULL;
+
+	return sysinfo_format_memory (totalmem, freemem);
+}
+
+char *
+sysinfo_backend_get_cpu(void)
+{
+	guint64 cpu_clock_uint = 0;
+	double cpu_clock;
+	char cpu_string[256];
+	gsize len;
+	gboolean giga = FALSE;
+
+	len = sizeof(cpu_string);
+	if (sysctlbyname ("machdep.cpu.brand_string", cpu_string, &len, NULL, 0) != 0)
+		return NULL;
+	cpu_string[sizeof(cpu_string) - 1] = '\0';
+
+	len = sizeof(cpu_clock_uint);
+	if (sysctlbyname("hw.cpufrequency", &cpu_clock_uint, &len, NULL, 0) < 0)
+		return NULL;
+
+	cpu_clock = cpu_clock_uint / 1000000;
+	if (cpu_clock > 1000)
+	{
+		cpu_clock /= 1000;
+		giga = TRUE;
+	}
+
+	if (giga)
+		return g_strdup_printf ("%s (%.2fGHz)", cpu_string, cpu_clock);
+	else
+		return g_strdup_printf ("%s (%.0fMHz)", cpu_string, cpu_clock);
+}
+
+static char *
+get_gpu(void)
+{
+	CFMutableDictionaryRef pciDevices = IOServiceMatching("IOPCIDevice");
+	io_iterator_t entry_iterator, serviceObject;
+
+	if (IOServiceGetMatchingServices(kIOMasterPortDefault, pciDevices, &entry_iterator) != kIOReturnSuccess)
+		return NULL;
+
+	GString *gpu_list = g_string_new(NULL);
+	while ((serviceObject = IOIteratorNext(entry_iterator)))
+	{
+		CFMutableDictionaryRef serviceDictionary;
+
+		kern_return_t status = IORegistryEntryCreateCFProperties(serviceObject, &serviceDictionary,
+														 kCFAllocatorDefault, kNilOptions);
+
+		if (status != kIOReturnSuccess)
+		{
+			IOObjectRelease(serviceObject);
+			continue;
+		}
+
+		const void *class = CFDictionaryGetValue(serviceDictionary, @"class-code");
+		if (!class || *(guint32*)CFDataGetBytePtr(class) != 0x30000) /* DISPLAY_VGA */
+		{
+			CFRelease(serviceDictionary);
+			continue;
+		}
+
+		const void *model = CFDictionaryGetValue(serviceDictionary, @"model");
+		if (model)
+		{
+			if (CFGetTypeID(model) == CFDataGetTypeID() && CFDataGetLength(model) > 1)
+			{
+				if (gpu_list->len != 0)
+						g_string_append (gpu_list, ", ");
+				g_string_append_len (gpu_list, (const char*)CFDataGetBytePtr(model), CFDataGetLength(model) - 1);
+			}
+		}
+
+		CFRelease(serviceDictionary);
+	}
+
+	if (gpu_list->len == 0)
+	{
+		g_string_free (gpu_list, TRUE);
+		return NULL;
+	}
+
+	/* The string may contain nul-chars we must replace */
+	int i;
+	for (i = 0; i < gpu_list->len; i++)
+	{
+		if (gpu_list->str[i] == '\0')
+			gpu_list->str[i] = ' ';
+	}
+
+	return g_string_free (gpu_list, FALSE);
+}
+
+char *
+sysinfo_backend_get_gpu(void)
+{
+	static char *gpu_str = NULL;
+	if (!gpu_str)
+		gpu_str = get_gpu();
+
+	return g_strdup (gpu_str);
+}
+
+char *
+sysinfo_backend_get_sound(void)
+{
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_uptime(void)
+{
+	NSProcessInfo *info = [NSProcessInfo processInfo];
+	double uptime = [info systemUptime];
+
+	return sysinfo_format_uptime ((gint64)uptime);
+}
+
+char *
+sysinfo_backend_get_network(void)
+{
+	return NULL;
+}
diff --git a/plugins/sysinfo/pci.c b/plugins/sysinfo/pci.c
deleted file mode 100644
index bc8fb11f..00000000
--- a/plugins/sysinfo/pci.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * pci.c - PCI functions for X-Sys
- * Copyright (C) 1997-1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz> [PCI routines from lspci]
- * Copyright (C) 2000 Tom Rini <trini@kernel.crashing.org> [XorgAutoConfig pci.c, based on lspci]
- * Copyright (C) 2005, 2006 Tony Vroon
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <pci/pci.h>
-#include "xsys.h"
-
-static struct pci_filter filter;       /* Device filter */
-static struct pci_access *pacc;
-int bus, dev, func; /* Location of the card */
-
-struct device {
-  	struct device *next;
-  	struct pci_dev *dev;
-  	unsigned int config_cnt;
-  	u8 config[256];
-};
-
-static struct device *first_dev;
-
-static struct device *scan_device(struct pci_dev *p)
-{
-  	int how_much = 64;
-  	struct device *d;
-
-  	if (!pci_filter_match(&filter, p))
-    		return NULL;
-  	d = malloc(sizeof(struct device));
-  	bzero(d, sizeof(*d));
-  	d->dev = p;
-  	if (!pci_read_block(p, 0, d->config, how_much))
-    		exit(1);
-  	if (how_much < 128 && (d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS) {
-      		/* For cardbus bridges, we need to fetch 64 bytes more to get the full standard header... */
-      		if (!pci_read_block(p, 64, d->config+64, 64))
-        		exit(1);
-      		how_much = 128;
-    	}
-  	d->config_cnt = how_much;
-  	pci_setup_cache(p, d->config, d->config_cnt);
-  	pci_fill_info(p, PCI_FILL_IDENT);
-  	return d;
-}
-
-static void scan_devices(void)
-{
-  	struct device *d;
-  	struct pci_dev *p;
-
-  	pci_scan_bus(pacc);
-  	for(p=pacc->devices; p; p=p->next)
-    	if ((d = scan_device(p))) {
-        	d->next = first_dev;
-        	first_dev = d;
-      	}
-}
-
-static u16 get_conf_word(struct device *d, unsigned int pos)
-{
-  	return d->config[pos] | (d->config[pos+1] << 8);
-}
-
-int pci_find_by_class(u16 *class, char *vendor, char *device)
-{
-	struct device *d;
-	struct pci_dev *p;
-	int nomatch = 1;
-
-	pacc = pci_alloc();
-	pci_filter_init(pacc, &filter);
-	pci_init(pacc);
-	scan_devices();
-
-	for(d=first_dev; d; d=d->next) {
-    		p = d->dev;
-    		/* Acquire vendor & device ID if the class matches */
-    		if(get_conf_word(d, PCI_CLASS_DEVICE) == *class) {
-      			nomatch = 0;
-			snprintf(vendor,7,"%04x",p->vendor_id);
-			snprintf(device,7,"%04x",p->device_id);
-      			break;
-    		}
-  	}
-
-  	pci_cleanup(pacc);
-  	return nomatch;
-}
-
-void pci_find_fullname(char *fullname, char *vendor, char *device)
-{
-	char buffer[bsize];
-	char vendorname[bsize/2] = "";
-	char devicename[bsize/2] = "";
-	char *position;
-	int cardfound = 0;
-
-	sysinfo_get_pciids (buffer);
-	FILE *fp = fopen (buffer, "r");
-
-	if(fp == NULL) {
-		snprintf(fullname, bsize, "%s:%s", vendor, device);
-		sysinfo_print_error ("pci.ids file not found! You might want to adjust your pciids setting with /SYSINFO SET pciids (you can query its current value with /SYSINFO LIST).\n");
-		return;
-	}
-
-	while(fgets(buffer, bsize, fp) != NULL)	{
-		if (!isspace(buffer[0]) && strstr(buffer, vendor) != NULL) {
-                       	position = strstr(buffer, vendor);
-                       	position += 6;
-                       	strncpy(vendorname, position, bsize/2);
-                       	position = strstr(vendorname, "\n");
-                       	*(position) = '\0';
-			break;
-                }
-	}
-	while(fgets(buffer, bsize, fp) != NULL) {
-		if(strstr(buffer, device) != NULL) {
-                        position = strstr(buffer, device);
-                        position += 6;
-                        strncpy(devicename, position, bsize/2);
-			position = strstr(devicename, " (");
-			if (position == NULL)
-                        	position = strstr(devicename, "\n");
-                        *(position) = '\0';
-			cardfound = 1;
-			break;
- 		}
-	}
-	if (cardfound == 1)
-		snprintf(fullname, bsize, "%s %s", vendorname, devicename);
-	else
-		snprintf(fullname, bsize, "%s:%s", vendor, device);	
-	fclose(fp);
-}
diff --git a/plugins/sysinfo/shared/df.c b/plugins/sysinfo/shared/df.c
new file mode 100644
index 00000000..ce0760a6
--- /dev/null
+++ b/plugins/sysinfo/shared/df.c
@@ -0,0 +1,53 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include "sysinfo.h"
+
+int xs_parse_df(gint64 *out_total, gint64 *out_free)
+{
+	FILE *pipe;
+	char buffer[bsize];
+	
+	pipe = popen("df -k -l -P", "r");
+	if(pipe==NULL)
+		return 1;
+
+	*out_total = *out_free = 0;
+
+	while(fgets(buffer, bsize, pipe) != NULL)
+	{
+		long long int avail, total;
+
+		/* Filesystem 1024-blocks Used Available Capacity Mounted-on */
+		if (sscanf (buffer, "%*s %lld %*s %lld %*s %*s", &total, &avail) == 2)
+		{
+			*out_total += total;
+			*out_free += avail;
+		}
+	}
+
+	/* Convert to bytes */
+	*out_total *= 1000;
+	*out_free *= 1000;
+
+	pclose(pipe);
+	return 0;
+}
diff --git a/plugins/sysinfo/shared/df.h b/plugins/sysinfo/shared/df.h
new file mode 100644
index 00000000..5f7f3296
--- /dev/null
+++ b/plugins/sysinfo/shared/df.h
@@ -0,0 +1,23 @@
+/*
+ * 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
+ */
+
+
+#ifndef SYSINFO_SHARED_H
+#define SYSINFO_SHARED_H
+
+int xs_parse_df(gint64 *total_bytes, gint64 *free_bytes);
+
+#endif
diff --git a/plugins/sysinfo/sysinfo-backend.h b/plugins/sysinfo/sysinfo-backend.h
new file mode 100644
index 00000000..c69a0853
--- /dev/null
+++ b/plugins/sysinfo/sysinfo-backend.h
@@ -0,0 +1,33 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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
+ */
+
+
+#ifndef SYSINFO_BACKEND_H
+#define SYSINFO_BACKEND_H
+
+char *sysinfo_backend_get_os(void);
+char *sysinfo_backend_get_disk(void);
+char *sysinfo_backend_get_memory(void);
+char *sysinfo_backend_get_cpu(void);
+char *sysinfo_backend_get_gpu(void);
+char *sysinfo_backend_get_sound(void);
+char *sysinfo_backend_get_uptime(void);
+char *sysinfo_backend_get_network(void);
+
+#endif
diff --git a/plugins/sysinfo/sysinfo.c b/plugins/sysinfo/sysinfo.c
new file mode 100644
index 00000000..10c9d796
--- /dev/null
+++ b/plugins/sysinfo/sysinfo.c
@@ -0,0 +1,277 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2012 Berke Viktor.
+ *
+ * xsys.c - main functions for X-Sys 2
+ * by mikeshoup
+ * Copyright (C) 2003, 2004, 2005 Michael Shoup
+ * Copyright (C) 2005, 2006, 2007 Tony Vroon
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include "hexchat-plugin.h"
+#include "sysinfo-backend.h"
+#include "sysinfo.h"
+
+#define _(x) hexchat_gettext(ph,x)
+#define DEFAULT_ANNOUNCE TRUE
+
+static hexchat_plugin *ph;
+
+static char name[] = "Sysinfo";
+static char desc[] = "Display info about your hardware and OS";
+static char version[] = "1.0";
+static char sysinfo_help[] = "SysInfo Usage:\n  /SYSINFO [-e|-o] [CLIENT|OS|CPU|RAM|DISK|VGA|SOUND|ETHERNET|UPTIME], print various details about your system or print a summary without arguments\n  /SYSINFO SET <variable>\n";
+
+typedef struct
+{
+	const char *name; /* Lower case name used for prefs */
+	const char *title; /* Used for the end formatting */
+	char *(*callback) (void);
+	gboolean def; /* Hide by default? */
+} hwinfo;
+
+static char *
+get_client (void)
+{
+	return g_strdup_printf ("HexChat %s", hexchat_get_info(ph, "version"));
+}
+
+static hwinfo hwinfos[] = {
+	{"client", "Client", get_client},
+	{"os", "OS", sysinfo_backend_get_os},
+	{"cpu", "CPU", sysinfo_backend_get_cpu},
+	{"memory", "Memory", sysinfo_backend_get_memory},
+	{"storage", "Storage", sysinfo_backend_get_disk},
+	{"vga", "VGA", sysinfo_backend_get_gpu},
+	{"sound", "Sound", sysinfo_backend_get_sound, TRUE},
+	{"ethernet", "Ethernet", sysinfo_backend_get_network, TRUE},
+	{"uptime", "Uptime", sysinfo_backend_get_uptime},
+	{NULL, NULL},
+};
+
+static gboolean sysinfo_get_bool_pref (const char *pref, gboolean def);
+
+static gboolean
+should_show_info (hwinfo info)
+{
+	char hide_pref[32];
+
+	g_snprintf (hide_pref, sizeof(hide_pref), "hide_%s", info.name);
+	return !sysinfo_get_bool_pref (hide_pref, info.def);
+}
+
+static void
+print_summary (gboolean announce)
+{
+	char **strings = g_new0 (char*, G_N_ELEMENTS(hwinfos));
+	int i, x;
+	char *output;
+
+	for (i = 0, x = 0; hwinfos[i].name != NULL; i++)
+	{
+		if (should_show_info (hwinfos[i]))
+		{
+			char *str = hwinfos[i].callback();
+			if (str)
+			{
+				strings[x++] = g_strdup_printf ("\002%s\002: %s", hwinfos[i].title, str);
+				g_free (str);
+			}
+		}
+	}
+
+	output = g_strjoinv (" \002\342\200\242\002 ", strings);
+	hexchat_commandf (ph, "%s %s", announce ? "SAY" : "ECHO", output);
+
+	g_strfreev (strings);
+	g_free (output);
+}
+
+static void
+print_info (char *info, gboolean announce)
+{
+	int i;
+
+	for (i = 0; hwinfos[i].name != NULL; i++)
+	{
+		if (!g_ascii_strcasecmp (info, hwinfos[i].name))
+		{
+			char *str = hwinfos[i].callback();
+			if (str)
+			{
+				hexchat_commandf (ph, "%s \002%s\002: %s", announce ? "SAY" : "ECHO",
+									hwinfos[i].title, str);
+				g_free (str);
+			}
+			else
+				hexchat_print (ph, _("Sysinfo: Failed to get info. Either not supported or error."));
+			return;
+		}
+	}
+
+	hexchat_print (ph, _("Sysinfo: No info by that name\n"));
+}
+
+/*
+ * Simple wrapper for backend specific options.
+ * Ensure dest >= 512.
+ */
+int
+sysinfo_get_str_pref (const char *pref, char *dest)
+{
+	return hexchat_pluginpref_get_str (ph, pref, dest);
+}
+
+static gboolean
+sysinfo_get_bool_pref (const char *pref, gboolean def)
+{
+	int value = hexchat_pluginpref_get_int (ph, pref);
+
+	if (value != -1)
+		return value;
+
+	return def;
+}
+
+static void
+sysinfo_set_pref_real (const char *pref, char *value, gboolean def)
+{
+	if (value && value[0])
+	{
+		guint64 i = g_ascii_strtoull (value, NULL, 0);
+		hexchat_pluginpref_set_int (ph, pref, i != 0);
+		hexchat_printf (ph, _("Sysinfo: %s is set to: %d\n"), pref, i != 0);
+	}
+	else
+	{
+		hexchat_printf (ph, _("Sysinfo: %s is set to: %d\n"), pref,
+						sysinfo_get_bool_pref(pref, def));
+	}
+}
+
+static void
+sysinfo_set_pref (char *key, char *value)
+{
+	if (!key || !key[0])
+	{
+		hexchat_print (ph, _("Sysinfo: Valid settings are: announce and hide_* for each piece of information. e.g. hide_os. Without a value it will show current (or default) setting.\n"));
+		return;
+	}
+
+	if (!strcmp (key, "announce"))
+	{
+		sysinfo_set_pref_real (key, value, DEFAULT_ANNOUNCE);
+		return;
+	}
+#ifdef HAVE_LIBPCI
+	else if (!strcmp (key, "pciids"))
+	{
+		if (value && value[0])
+		{
+			hexchat_pluginpref_set_str (ph, "pciids", value);
+			hexchat_printf (ph, _("Sysinfo: pciids is set to: %s\n"), value);
+		}
+		else
+		{
+			char buf[512];
+			if (hexchat_pluginpref_get_str (ph, "pciids", buf) == 0)
+				strcpy (buf, DEFAULT_PCIIDS);
+			hexchat_printf (ph, _("Sysinfo: pciids is set to: %s\n"), buf);
+		}
+		return;
+	}
+#endif
+	else if (g_str_has_prefix (key, "hide_"))
+	{
+		int i;
+		for (i = 0; hwinfos[i].name != NULL; i++)
+		{
+			if (!strcmp (key + 5, hwinfos[i].name))
+			{
+				sysinfo_set_pref_real (key, value, hwinfos[i].def);
+				return;
+			}
+		}
+	}
+
+	hexchat_print (ph, _("Sysinfo: Invalid variable name\n"));
+}
+
+static int
+sysinfo_cb (char *word[], char *word_eol[], void *userdata)
+{
+	gboolean announce = sysinfo_get_bool_pref("announce", DEFAULT_ANNOUNCE);
+	int offset = 0, channel_type;
+	char *cmd;
+
+	/* Allow overriding global announce setting */
+	if (!strcmp ("-e", word[2]))
+	{
+		announce = FALSE;
+		offset++;
+	}
+	else if (!strcmp ("-o", word[2]))
+	{
+		announce = TRUE;
+		offset++;
+	}
+
+	/* Cannot send to server tab */
+	channel_type = hexchat_list_int (ph, NULL, "type");
+	if (channel_type != 2 /* SESS_CHANNEL */ && channel_type != 3 /* SESS_DIALOG */)
+		announce = FALSE;
+
+	cmd = word[2+offset];
+	if (!g_ascii_strcasecmp ("SET", cmd))
+		sysinfo_set_pref (word[3+offset], word_eol[4+offset]);
+	else if (!cmd || !cmd[0])
+		print_summary (announce);
+	else
+		print_info (cmd, announce);
+
+	return HEXCHAT_EAT_ALL;
+}
+
+int
+hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
+{
+	ph = plugin_handle;
+	*plugin_name = name;
+	*plugin_desc = desc;
+	*plugin_version = version;
+
+	hexchat_hook_command (ph, "SYSINFO", HEXCHAT_PRI_NORM, sysinfo_cb, sysinfo_help, NULL);
+
+	hexchat_command (ph, "MENU ADD \"Window/Send System Info\" \"SYSINFO\"");
+	hexchat_printf (ph, _("%s plugin loaded\n"), name);
+	return 1;
+}
+
+int
+hexchat_plugin_deinit (void)
+{
+	hexchat_command (ph, "MENU DEL \"Window/Display System Info\"");
+	hexchat_printf (ph, _("%s plugin unloaded\n"), name);
+	return 1;
+}
diff --git a/plugins/sysinfo/sysinfo.cpp b/plugins/sysinfo/sysinfo.cpp
deleted file mode 100644
index 43ab48c0..00000000
--- a/plugins/sysinfo/sysinfo.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-/* HexChat
- * Copyright (c) 2011-2012 Berke Viktor.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <stdio.h>
-#include <windows.h>
-#include <comutil.h>
-#include <wbemidl.h>
-
-#include "hexchat-plugin.h"
-
-static hexchat_plugin *ph;   /* plugin handle */
-static char name[] = "SysInfo";
-static char desc[] = "Display info about your hardware and OS";
-static char version[] = "1.1";
-static char helptext[] = "USAGE: /sysinfo - Sends info about your hardware and OS to current channel.";
-static int firstRun;
-static char *wmiOs;
-static char *wmiCpu;
-static char *wmiVga;
-
-static int
-getCpuArch (void)
-{
-	OSVERSIONINFOEX osvi;
-	SYSTEM_INFO si;
-
-	osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
-	GetVersionEx ((LPOSVERSIONINFOW) &osvi);
-
-	GetSystemInfo (&si);
-
-	if (si.wProcessorArchitecture == 9)
-	{
-		return 64;
-	}
-	else
-	{
-		return 86;
-	}
-}
-
-#if 0
-/* use WMI instead, wProcessorArchitecture displays current binary arch instead of OS arch anyway */
-static char *
-getOsName (void)
-{
-	static char winver[32];
-	double mhz;
-	OSVERSIONINFOEX osvi;
-	SYSTEM_INFO si;
-
-	osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
-	GetVersionEx ((LPOSVERSIONINFOW) &osvi);
-
-	GetSystemInfo (&si);
-
-	strcpy (winver, "Windows ");
-
-	switch (osvi.dwMajorVersion)
-	{
-		case 5:
-			switch (osvi.dwMinorVersion)
-			{
-				case 1:
-					strcat (winver, "XP");
-					break;
-				case 2:
-					if (osvi.wProductType == VER_NT_WORKSTATION)
-					{
-						strcat (winver, "XP x64 Edition");
-					}
-					else
-					{
-						if (GetSystemMetrics(SM_SERVERR2) == 0)
-						{
-							strcat (winver, "Server 2003");
-						}
-						else
-						{
-							strcat (winver, "Server 2003 R2");
-						}
-					}
-					break;
-			}
-			break;
-		case 6:
-			switch (osvi.dwMinorVersion)
-			{
-				case 0:
-					if (osvi.wProductType == VER_NT_WORKSTATION)
-					{
-						strcat (winver, "Vista");
-					}
-					else
-					{
-						strcat (winver, "Server 2008");
-					}
-					break;
-				case 1:
-					if (osvi.wProductType == VER_NT_WORKSTATION)
-					{
-						strcat (winver, "7");
-					}
-					else
-					{
-						strcat (winver, "Server 2008 R2");
-					}
-					break;
-				case 2:
-					if (osvi.wProductType == VER_NT_WORKSTATION)
-					{
-						strcat (winver, "8");
-					}
-					else
-					{
-						strcat (winver, "8 Server");
-					}
-					break;
-			}
-			break;
-	}
-
-	if (si.wProcessorArchitecture == 9)
-	{
-		strcat (winver, " (x64)");
-	}
-	else
-	{
-		strcat (winver, " (x86)");
-	}
-
-	return winver;
-}
-
-/* x86-only, SDK-only, use WMI instead */
-static char *
-getCpuName (void)
-{
-	// Get extended ids.
-	unsigned int nExIds;
-	unsigned int i;
-	int CPUInfo[4] = {-1};
-	static char CPUBrandString[128];
-
-	__cpuid (CPUInfo, 0x80000000);
-	nExIds = CPUInfo[0];
-
-	/* Get the information associated with each extended ID. */
-	for (i=0x80000000; i <= nExIds; ++i)
-	{
-		__cpuid (CPUInfo, i);
-
-		if (i == 0x80000002)
-		{
-			memcpy (CPUBrandString, CPUInfo, sizeof (CPUInfo));
-		}
-		else if (i == 0x80000003)
-		{
-			memcpy( CPUBrandString + 16, CPUInfo, sizeof (CPUInfo));
-		}
-		else if (i == 0x80000004)
-		{
-			memcpy (CPUBrandString + 32, CPUInfo, sizeof (CPUInfo));
-		}
-	}
-
-	return CPUBrandString;
-}
-#endif
-
-static char *
-getCpuMhz (void)
-{
-	HKEY hKey;
-	int result;
-	int data;
-	int dataSize;
-	double cpuspeed;
-	static char buffer[16];
-	const char *cpuspeedstr;
-
-	if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("Hardware\\Description\\System\\CentralProcessor\\0"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
-	{
-		dataSize = sizeof (data);
-		result = RegQueryValueEx (hKey, TEXT("~MHz"), 0, 0, (LPBYTE)&data, (LPDWORD)&dataSize);
-		RegCloseKey (hKey);
-		if (result == ERROR_SUCCESS)
-		{
-			cpuspeed = ( data > 1000 ) ? data / 1000 : data;
-			cpuspeedstr = ( data > 1000 ) ? "GHz" : "MHz";
-			sprintf (buffer, "%.2f %s", cpuspeed, cpuspeedstr);
-		}
-	}
-
-	return buffer;
-}
-
-static char *
-getMemoryInfo (void)
-{
-	static char buffer[32];
-	MEMORYSTATUSEX meminfo;
-
-	meminfo.dwLength = sizeof (meminfo);
-	GlobalMemoryStatusEx (&meminfo);
-
-	sprintf (buffer, "%I64d MB Total (%I64d MB Free)", meminfo.ullTotalPhys / 1024 / 1024, meminfo.ullAvailPhys / 1024 / 1024);
-
-	return buffer;
-}
-
-static char *
-getWmiInfo (int mode)
-{
-	/* for more details about this wonderful API, see 
-	http://msdn.microsoft.com/en-us/site/aa394138
-	http://msdn.microsoft.com/en-us/site/aa390423
-	http://msdn.microsoft.com/en-us/library/windows/desktop/aa394138%28v=vs.85%29.aspx
-	http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/d6420012-e432-4964-8506-6f6b65e5a451
-	*/
-
-	char *buffer = (char *) malloc (128);
-	HRESULT hres;
-	HRESULT hr;
-	IWbemLocator *pLoc = NULL;
-	IWbemServices *pSvc = NULL;
-	IEnumWbemClassObject *pEnumerator = NULL;
-	IWbemClassObject *pclsObj;
-	ULONG uReturn = 0;
-
-	hres =  CoInitializeEx (0, COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY);
-
-	if (FAILED (hres))
-	{
-		strcpy (buffer, "Error Code 0");
-		return buffer;
-	}
-
-	hres =  CoInitializeSecurity (NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
-
-	/* mysteriously failing after the first execution, but only when used as a plugin, skip it */
-	/*if (FAILED (hres))
-	{
-		CoUninitialize ();
-		strcpy (buffer, "Error Code 1");
-		return buffer;
-	}*/
-
-	hres = CoCreateInstance (CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc);
-
-	if (FAILED (hres))
-	{
-		CoUninitialize ();
-		strcpy (buffer, "Error Code 2");
-		return buffer;
-	}
-
-	hres = pLoc->ConnectServer (_bstr_t (L"root\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
-
-	if (FAILED (hres))
-	{
-		pLoc->Release ();
-		CoUninitialize ();
-		strcpy (buffer, "Error Code 3");
-		return buffer;
-	}
-
-	hres = CoSetProxyBlanket (pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
-
-	if (FAILED (hres))
-	{
-		pSvc->Release ();
-		pLoc->Release ();
-		CoUninitialize ();
-		strcpy (buffer, "Error Code 4");
-		return buffer;
-	}
-
-	switch (mode)
-	{
-		case 0:
-			hres = pSvc->ExecQuery (_bstr_t ("WQL"), _bstr_t ("SELECT * FROM Win32_OperatingSystem"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
-			break;
-		case 1:
-			hres = pSvc->ExecQuery (_bstr_t ("WQL"), _bstr_t ("SELECT * FROM Win32_Processor"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
-			break;
-		case 2:
-			hres = pSvc->ExecQuery (_bstr_t ("WQL"), _bstr_t ("SELECT * FROM Win32_VideoController"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
-			break;
-
-	}
-
-	if (FAILED (hres))
-	{
-		pSvc->Release ();
-		pLoc->Release ();
-		CoUninitialize ();
-		strcpy (buffer, "Error Code 5");
-		return buffer;
-	}
-
-	while (pEnumerator)
-	{
-		hr = pEnumerator->Next (WBEM_INFINITE, 1, &pclsObj, &uReturn);
-		if (0 == uReturn)
-		{
-			break;
-		}
-		VARIANT vtProp;
-		switch (mode)
-		{
-			case 0:
-				hr = pclsObj->Get (L"Caption", 0, &vtProp, 0, 0);
-				break;
-			case 1:
-				hr = pclsObj->Get (L"Name", 0, &vtProp, 0, 0);
-				break;
-			case 2:
-				hr = pclsObj->Get (L"Name", 0, &vtProp, 0, 0);
-				break;
-		}
-		WideCharToMultiByte (CP_ACP, 0, vtProp.bstrVal, -1, buffer, SysStringLen (vtProp.bstrVal)+1, NULL, NULL);
-		VariantClear (&vtProp);
-    }
-
-	pSvc->Release ();
-	pLoc->Release ();
-	pEnumerator->Release ();
-	pclsObj->Release ();
-	CoUninitialize ();
-	return buffer;
-}
-
-static int
-printInfo (char *word[], char *word_eol[], void *user_data)
-{
-	/* query WMI info only at the first time SysInfo is called, then cache it to save time */
-	if (firstRun)
-	{
-		hexchat_printf (ph, "%s first execution, querying and caching WMI info...\n", name);
-		wmiOs = getWmiInfo (0);
-		wmiCpu = getWmiInfo (1);
-		wmiVga = getWmiInfo (2);
-		firstRun = 0;
-	}
-	if (hexchat_list_int (ph, NULL, "type") >= 2)
-	{
-		/* uptime will work correctly for up to 50 days, should be enough */
-		hexchat_commandf (ph, "ME ** SysInfo ** Client: HexChat %s (x%d) ** OS: %s ** CPU: %s (%s) ** RAM: %s ** VGA: %s ** Uptime: %.2f Hours **",
-			hexchat_get_info (ph, "version"),
-			getCpuArch (),
-			wmiOs,
-			wmiCpu,
-			getCpuMhz (),
-			getMemoryInfo (),
-			wmiVga, (float) GetTickCount() / 1000 / 60 / 60);
-	}
-	else
-	{
-		hexchat_printf (ph, " * Client:  HexChat %s (x%d)\n", hexchat_get_info (ph, "version"), getCpuArch ());
-		hexchat_printf (ph, " * OS:      %s\n", wmiOs);
-		hexchat_printf (ph, " * CPU:     %s (%s)\n", wmiCpu, getCpuMhz ());
-		hexchat_printf (ph, " * RAM:     %s\n", getMemoryInfo ());
-		hexchat_printf (ph, " * VGA:     %s\n", wmiVga);
-		hexchat_printf (ph, " * Uptime:  %.2f Hours\n", (float) GetTickCount() / 1000 / 60 / 60);
-	}
-
-	return HEXCHAT_EAT_HEXCHAT;
-}
-
-int
-hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
-{
-	ph = plugin_handle;
-
-	*plugin_name = name;
-	*plugin_desc = desc;
-	*plugin_version = version;
-
-	firstRun = 1;
-
-	hexchat_hook_command (ph, "SYSINFO", HEXCHAT_PRI_NORM, printInfo, helptext, NULL);
-	hexchat_command (ph, "MENU -ishare\\system.png ADD \"Window/Send System Info\" \"SYSINFO\"");
-
-	hexchat_printf (ph, "%s plugin loaded\n", name);
-
-	return 1;       /* return 1 for success */
-}
-
-
-int
-hexchat_plugin_deinit (void)
-{
-	hexchat_command (ph, "MENU DEL \"Window/Display System Info\"");
-	hexchat_printf (ph, "%s plugin unloaded\n", name);
-	return 1;
-}
diff --git a/plugins/sysinfo/hwmon.h b/plugins/sysinfo/sysinfo.h
index fe71274b..cfde8408 100644
--- a/plugins/sysinfo/hwmon.h
+++ b/plugins/sysinfo/sysinfo.h
@@ -1,6 +1,6 @@
 /*
- * hwmon.h - Hardware monitoring header for X-Sys
- * Copyright (C) 2005 Tony Vroon
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
  *
  * 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
@@ -18,11 +18,12 @@
  */
 
 
-#ifndef _HWMON_H_
-#define _HWMON_H_
+#ifndef SYSINFO_H
+#define SYSINFO_H
 
-int hwmon_chip_present();
-void get_hwmon_chip_name(char *name);
-void get_hwmon_temp(unsigned int *value, unsigned int *sensor);
+#define bsize 1024
+#define DEFAULT_PCIIDS "/usr/share/hwdata/pci.ids"
+
+int sysinfo_get_str_pref (const char *name, char *dest);
 
 #endif
diff --git a/plugins/sysinfo/sysinfo.vcxproj b/plugins/sysinfo/sysinfo.vcxproj
index 7286b89a..3d429295 100644
--- a/plugins/sysinfo/sysinfo.vcxproj
+++ b/plugins/sysinfo/sysinfo.vcxproj
@@ -2,6 +2,8 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>Unicode</CharacterSet>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,91 +21,51 @@
     <RootNamespace>sysinfo</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>Unicode</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>

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

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

+  <PropertyGroup>

     <TargetName>hcsysinfo</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hcsysinfo</TargetName>

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

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

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SYSINFO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>..\..\src\common;$(DepsRoot)\include;$(Glib);$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

       <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <ModuleDefinitionFile>sysinfo.def</ModuleDefinitionFile>

-      <AdditionalDependencies>wbemuuid.lib;comsupp.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>wbemuuid.lib;comsupp.lib;$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <IgnoreSpecificDefaultLibraries>comsupp.lib</IgnoreSpecificDefaultLibraries>

+      <ModuleDefinitionFile>sysinfo.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;SYSINFO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <AdditionalIncludeDirectories>..\..\src\common;$(DepsRoot)\include;$(Glib);$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

       <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <ModuleDefinitionFile>sysinfo.def</ModuleDefinitionFile>

-      <AdditionalDependencies>wbemuuid.lib;comsupp.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>wbemuuid.lib;comsupp.lib;$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

       <IgnoreSpecificDefaultLibraries>comsupp.lib</IgnoreSpecificDefaultLibraries>

+      <ModuleDefinitionFile>sysinfo.def</ModuleDefinitionFile>

     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

     <None Include="sysinfo.def" />

   </ItemGroup>

   <ItemGroup>

-    <ClCompile Include="sysinfo.cpp" />

+    <ClCompile Include="format.c" />

+    <ClCompile Include="sysinfo.c" />

+    <ClCompile Include="win32\backend.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="format.h" />

+    <ClInclude Include="sysinfo-backend.h" />

+    <ClInclude Include="sysinfo.h" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/sysinfo/sysinfo.vcxproj.filters b/plugins/sysinfo/sysinfo.vcxproj.filters
index 1ef90f5b..aa173bb5 100644
--- a/plugins/sysinfo/sysinfo.vcxproj.filters
+++ b/plugins/sysinfo/sysinfo.vcxproj.filters
@@ -9,6 +9,9 @@
       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>

       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>

     </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{c873eb6b-aca6-434d-8ec9-199838b80838}</UniqueIdentifier>

+    </Filter>

   </ItemGroup>

   <ItemGroup>

     <None Include="sysinfo.def">

@@ -16,8 +19,25 @@
     </None>

   </ItemGroup>

   <ItemGroup>

-    <ClCompile Include="sysinfo.cpp">

+    <ClCompile Include="sysinfo.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="win32\backend.c">

       <Filter>Source Files</Filter>

     </ClCompile>

+    <ClCompile Include="format.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="sysinfo.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="sysinfo-backend.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="format.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

   </ItemGroup>

 </Project>
\ No newline at end of file
diff --git a/plugins/sysinfo/unix/backend.c b/plugins/sysinfo/unix/backend.c
new file mode 100644
index 00000000..dc065518
--- /dev/null
+++ b/plugins/sysinfo/unix/backend.c
@@ -0,0 +1,170 @@
+/*
+ * SysInfo - sysinfo plugin for HexChat
+ * Copyright (c) 2015 Patrick Griffis.
+ *
+ * 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 <glib.h>
+#include "parse.h"
+#include "match.h"
+#include "sysinfo.h"
+#include "format.h"
+#include "df.h"
+
+char *sysinfo_backend_get_os(void)
+{
+	char name[bsize];
+
+	if (xs_parse_distro (name) != 0)
+	{
+		return NULL;
+	}
+
+	return g_strdup(name);
+}
+
+char *sysinfo_backend_get_disk(void)
+{
+	gint64 total, free;
+
+	if (xs_parse_df (&total, &free))
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_disk (total, free);
+}
+
+char *sysinfo_backend_get_memory(void)
+{
+	unsigned long long mem_total;
+	unsigned long long mem_free;
+	unsigned long long swap_total;
+	unsigned long long swap_free;
+	char *swap_fmt = NULL, *mem_fmt, *ret;
+
+	if (xs_parse_meminfo (&mem_total, &mem_free, 0) == 1)
+	{
+		return NULL;
+	}
+	if (xs_parse_meminfo (&swap_total, &swap_free, 1) != 1)
+	{
+		swap_fmt = sysinfo_format_memory (swap_total, swap_free);
+	}
+
+	mem_fmt = sysinfo_format_memory (mem_total, mem_free);
+
+	if (swap_fmt)
+	{
+		ret = g_strdup_printf ("Physical: %s Swap: %s", mem_fmt, swap_fmt);
+		g_free (mem_fmt);
+		g_free (swap_fmt);
+	}
+	else
+		ret = mem_fmt;
+
+	return ret;
+}
+
+char *sysinfo_backend_get_cpu(void)
+{
+	char model[bsize];
+	char vendor[bsize];
+	char buffer[bsize];
+	double freq;
+	int giga = 0;
+
+	if (xs_parse_cpu (model, vendor, &freq) != 0)
+	{
+		return NULL;
+	}
+
+	if (freq > 1000)
+	{
+		freq /= 1000;
+		giga = 1;
+	}
+
+	if (giga)
+	{
+		g_snprintf (buffer, bsize, "%s (%.2fGHz)", model, freq);
+	}
+	else
+	{
+		g_snprintf (buffer, bsize, "%s (%.0fMHz)", model, freq);
+	}
+	
+	return g_strdup (buffer);
+}
+
+char *sysinfo_backend_get_gpu(void)
+{
+	char vid_card[bsize];
+	char agp_bridge[bsize];
+	char buffer[bsize];
+	int ret;
+
+	if ((ret = xs_parse_video (vid_card)) != 0)
+	{
+		return NULL;
+	}
+
+	if (xs_parse_agpbridge (agp_bridge) != 0)
+	{
+		g_snprintf (buffer, bsize, "%s", vid_card);
+	}
+	else
+	{
+		g_snprintf (buffer, bsize, "%s @ %s", vid_card, agp_bridge);
+	}
+
+	return g_strdup (buffer);
+}
+
+char *sysinfo_backend_get_sound(void)
+{
+	char sound[bsize];
+
+	if (xs_parse_sound (sound) != 0)
+	{
+		return NULL;
+	}
+	return g_strdup (sound);
+}
+
+char *sysinfo_backend_get_uptime(void)
+{
+	gint64 uptime;
+
+	if ((uptime = xs_parse_uptime ()) == 0)
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_uptime (uptime);
+}
+
+char *sysinfo_backend_get_network(void)
+{
+	char ethernet_card[bsize];
+
+	if (xs_parse_ether (ethernet_card))
+	{
+		g_strlcpy (ethernet_card, "None found", bsize);
+	}
+	
+	return g_strdup (ethernet_card);
+}
diff --git a/plugins/sysinfo/unix/match.c b/plugins/sysinfo/unix/match.c
new file mode 100644
index 00000000..2ef51f3f
--- /dev/null
+++ b/plugins/sysinfo/unix/match.c
@@ -0,0 +1,98 @@
+/*
+ * match.c - matching functions for X-Sys
+ * Copyright (C) 2005, 2006, 2007 Tony Vroon
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include "sysinfo.h"
+
+#define delims ":="
+
+void find_match_char(char *buffer, char *match, char *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+			position += 1;
+			strcpy(result, position);
+			position = strstr(result, "\n");
+			*(position) = '\0';
+			g_strchug(result);
+		}
+		else
+			strcpy(result, "\0");
+	}
+}
+
+void find_match_double(char *buffer, char *match, double *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+        	position += 1;
+        	*result = strtod(position, NULL);
+		}
+		else
+			*result = 0;
+	}
+}
+
+void find_match_double_hex(char *buffer, char *match, double *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+			memcpy(position,"0x",2);
+			*result = strtod(position,NULL);
+		}
+		else
+			*result = 0;
+	}
+}
+
+void find_match_ll(char *buffer, char *match, unsigned long long *result)
+{
+	char *position;
+	g_strchug(buffer);
+	if(strstr(buffer, match) == strstr(buffer, buffer))
+	{
+		position = strpbrk(buffer, delims);
+		if (position != NULL)
+		{
+			position += 1;
+			*result = strtoll(position, NULL, 10);
+		}
+		else
+			*result = 0;
+	}
+}
+
diff --git a/plugins/sysinfo/match.h b/plugins/sysinfo/unix/match.h
index 61811e4a..16999fa2 100644
--- a/plugins/sysinfo/match.h
+++ b/plugins/sysinfo/unix/match.h
@@ -23,13 +23,7 @@
 void find_match_char(char *buffer, char *match, char *result);
 void find_match_double(char *buffer, char *match, double *result);
 void find_match_double_hex(char *buffer, char *match, double *result);
-void find_match_int(char *buffer, char *match, unsigned int *result);
 void find_match_ll(char *buffer, char *match, unsigned long long *result);
-void format_output(const char *arg, char *string, char *format);
-void flat_format_output(const char *arg, char *string, char *format);
-float percentage(unsigned long long *free, unsigned long long *total);
-char *pretty_freespace(const char *desc, unsigned long long *free_k, unsigned long long *total_k);
 void remove_leading_whitespace(char *buffer);
-char *decruft_filename(char *buffer);
 
 #endif
diff --git a/plugins/sysinfo/parse.c b/plugins/sysinfo/unix/parse.c
index 4c15897a..f41f89a7 100644
--- a/plugins/sysinfo/parse.c
+++ b/plugins/sysinfo/unix/parse.c
@@ -23,19 +23,19 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-#include <time.h>
-#include <dirent.h>
-#include <sys/types.h>
 #include <pci/header.h>
+#include <glib.h>
+
+#ifdef __sparc__
+#include <dirent.h>
+#endif
 
 #include "pci.h"
 #include "match.h"
-#include "hwmon.h"
-#include "xsys.h"
+#include "parse.h"
+#include "sysinfo.h"
 
-int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned int *count)
+int xs_parse_cpu(char *model, char *vendor, double *freq)
 {
 #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__alpha__) || defined(__ia64__) || defined(__parisc__) || defined(__sparc__)
 	char buffer[bsize];
@@ -46,8 +46,6 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 	FILE *fp = fopen("/proc/cpuinfo", "r");
 	if(fp == NULL)
 		return 1;
-	if(count != NULL) *count = 0;
-	strcpy(cache,"unknown\0");
 	
 	#if defined(__i386__) || defined(__x86_64__)
 	while(fgets(buffer, bsize, fp) != NULL)
@@ -55,10 +53,7 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "model name", model);
 		find_match_char(buffer, "vendor_id", vendor);
 		find_match_double(buffer, "cpu MHz", freq);
-		find_match_char(buffer, "cache size", cache);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	#endif
 	#ifdef __powerpc__
 	while(fgets(buffer, bsize, fp) != NULL)
@@ -66,10 +61,7 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "cpu", model);
 		find_match_char(buffer, "machine", vendor);
 		find_match_double(buffer, "clock", freq);
-		find_match_char(buffer, "L2 cache", cache);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	pos = strstr(model, ",");
 	if (pos != NULL) *pos = '\0';
 	#endif
@@ -79,8 +71,6 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "cpu model", model);
 		find_match_char(buffer, "system type", vendor);
 		find_match_double(buffer, "cycle frequency [Hz]", freq);
-		find_match_char(buffer, "L2 cache", cache);
-		find_match_int(buffer, "cpus detected", count);
 	}
 	*freq = *freq / 1000000;
 	#endif
@@ -90,20 +80,15 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 		find_match_char(buffer, "model", model);
 		find_match_char(buffer, "vendor", vendor);
 		find_match_double(buffer, "cpu MHz", freq);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	#endif
 	#ifdef __parisc__
 	while(fgets(buffer, bsize, fp) != NULL)
 	{
 		find_match_char(buffer, "cpu  ", model);
 		find_match_char(buffer, "cpu family", vendor);
-		find_match_char(buffer, "D-cache", cache);
 		find_match_double(buffer, "cpu MHz", freq);
-		find_match_int(buffer, "processor", count);
 	}
-	*count = *count + 1;
 	#endif
 	#ifdef __sparc__
 	DIR *dir;
@@ -113,22 +98,8 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 	{
 		find_match_char(buffer, "cpu	", model);
 		find_match_char(buffer, "type	", vendor);
-		find_match_int(buffer, "ncpus active", count);
 		find_match_double_hex(buffer, "Cpu0ClkTck", freq);
 	}
-	/* Cache is tricky, only implemented for sparc64 */
-	if ((dir = opendir("/proc/openprom")) != NULL)
-		while ((entry = readdir(dir)) != NULL)
-			if (strncmp(entry->d_name,"SUNW,UltraSPARC",15) == 0)
-			{
-				snprintf(buffer,bsize,"/proc/openprom/%s/ecache-size",entry->d_name);
-				fp2 = fopen(buffer, "r");
-				if (fp2 == NULL) break;
-				fscanf(fp2,"%16s",cache);
-				fclose(fp2);
-				sprintf(buffer,"0x%s",cache);
-				sprintf(cache,"%0.0f KB",strtod(buffer,NULL)/1024);
-			}
 	*freq = *freq / 1000000;
 	#endif
 	fclose(fp);
@@ -136,43 +107,20 @@ int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned
 	return 0;
 }
 
-int xs_parse_uptime(int *weeks, int *days, int *hours, int *minutes, int *seconds)
+gint64 xs_parse_uptime(void)
 {
 	char buffer[bsize];
-	long long uptime = 0;
+	gint64 uptime = 0;
 	FILE *fp = fopen("/proc/uptime", "r");
 	if(fp == NULL)
-		return 1;
+		return 0;
 
 	if(fgets(buffer, bsize, fp) != NULL)
-		uptime = strtol(buffer, NULL, 0);
-	
-	*seconds = uptime%60;
-	*minutes = (uptime/60)%60;
-	*hours   = (uptime/3600)%24;
-	*days    = (uptime/86400)%7;
-	*weeks   = uptime/604800;
+		uptime = g_ascii_strtoll(buffer, NULL, 0);
 	
 	fclose(fp);
 	
-	return 0;
-}
-
-int xs_parse_os(char *user, char *host, char *kernel)
-{
-	struct utsname osinfo;
-	char hostn[bsize], *usern = getenv("USER");
-	
-	if(uname(&osinfo)<0)
-		return 1;	
-	if(gethostname(hostn, bsize)<0)
-		return 1;
-	
-	strncpy(user, usern, bsize);
-	strcpy(host, hostn);
-	snprintf(kernel, bsize, "%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine);
-	
-	return 0;
+	return uptime;
 }
 
 int xs_parse_sound(char *snd_card)
@@ -181,12 +129,13 @@ int xs_parse_sound(char *snd_card)
 	u16 class = PCI_CLASS_MULTIMEDIA_AUDIO;
 
 	FILE *fp = NULL;
-	if((fp = fopen("/proc/asound/cards", "r"))== NULL) {
+	if((fp = fopen("/proc/asound/cards", "r"))== NULL)
+	{
 		if (pci_find_by_class(&class, vendor, device) == 0) 
-			{
-				pci_find_fullname(snd_card, vendor, device);
-				return 0;
-			}
+		{
+			pci_find_fullname(snd_card, vendor, device);
+			return 0;
+		}
 		else
 			return 1;
 	}
@@ -197,13 +146,13 @@ int xs_parse_sound(char *snd_card)
 		if(isdigit(buffer[0]) || isdigit(buffer[1]))
 		{
 			char card_buf[bsize];
-			long card_id = 0;
+			gint64 card_id = 0;
 			pos = strstr(buffer, ":");
-			card_id = strtoll(buffer, NULL, 0);
+			card_id = g_ascii_strtoll(buffer, NULL, 0);
 			if (card_id == 0)
-				snprintf(card_buf, bsize, "%s", pos+2);
+				g_snprintf(card_buf, bsize, "%s", pos+2);
 			else
-				snprintf(card_buf, bsize, "%ld: %s", card_id, pos+2);
+				g_snprintf(card_buf, bsize, "%"G_GINT64_FORMAT": %s", card_id, pos+2);
 			pos = strstr(card_buf, "\n");
 			*pos = '\0';
 			strcat(cards, card_buf);
@@ -249,129 +198,42 @@ int xs_parse_agpbridge(char *agp_bridge)
 	return 0;
 }
 
-int xs_parse_netdev(const char *device, unsigned long long *bytes_recv, unsigned long long *bytes_sent)
-{
-	FILE *fp;
-	char buffer[bsize], *pos;
-	int i;
-	
-	fp=fopen("/proc/net/dev", "r");
-	if(fp==NULL)
-		return 1;
-	
-	while(fgets(buffer, bsize, fp) != NULL)
-	{
-		for(i=0; isspace(buffer[i]); i++);
-		if(strncmp(device, &buffer[i], strlen(device)) == 0) break;
-	}
-	fclose(fp);
-	pos = strstr(buffer, ":");
-	pos++;
-	*bytes_recv = strtoull(pos, &pos, 0);
-
-	for(i=0;i<7;i++) strtoull(pos, &pos, 0);
-	
-	*bytes_sent = strtoull(pos, NULL, 0);
-
-	return 0;
-}
-
-int xs_parse_df(const char *mount_point, char *result)
-{
-	FILE *pipe;
-	char buffer[bsize], *pos;
-	unsigned long long total_k=0, free_k=0;
-	int i=0;
-	
-	pipe = popen("df -k -l -P", "r");
-	if(pipe==NULL)
-		return 1;
-	
-	while(fgets(buffer, bsize, pipe) != NULL)
-	{
-		/* Skip over pseudo-filesystems and description line */
-		if(isalpha(buffer[0]))
-			continue;
-		
-		for(pos=buffer; !isspace(*pos); pos++);
-		for(;isspace(*pos);pos++);
-		if(mount_point == NULL)
-		{
-			total_k += strtoull(pos, &pos, 0);
-			strtoull(pos, &pos, 0);
-			free_k += strtoull(pos, &pos, 0);
-			continue;
-		}
-		total_k = strtoull(pos, &pos, 0);
-		strtoull(pos, &pos, 0);
-		free_k = strtoull(pos, &pos, 0);
-		strtoull(pos, &pos, 0);
-		for(;isspace(*pos);pos++);
-		for(;*pos!='/';pos++);
-		for(i=0;*(buffer+i)!='\n';i++);
-		*(buffer+i)='\0';
-		
-		if(strncasecmp(mount_point, "ALL", 3)==0)
-		{
-			char *tmp_buf = pretty_freespace(pos, &free_k, &total_k);
-			strcat(tmp_buf, " | ");
-			strcat(result, tmp_buf);
-			free(tmp_buf);
-		}
-		else if(strncmp(mount_point, pos, strlen(mount_point)) == 0)
-		{
-			char *tmp_buf = pretty_freespace(mount_point, &free_k, &total_k);
-			strncpy(result, tmp_buf, bsize);
-			free(tmp_buf);
-			break;
-		}
-		else snprintf(result, bsize, "Mount point %s not found!", mount_point);
-	}
-	
-	if(mount_point != NULL && strncasecmp(mount_point, "ALL", 3)==0)
-		*(result+strlen(result)-3) = '\0';
-	
-	if(mount_point == NULL)
-	{
-		char *tmp_buf = pretty_freespace("Total", &free_k, &total_k);
-		strncpy(result, tmp_buf, bsize);
-		free(tmp_buf);
-	}
-	pclose(pipe);
-	return 0;
-}
-
 int xs_parse_meminfo(unsigned long long *mem_tot, unsigned long long *mem_free, int swap)
 {
 	FILE *fp;
-        char buffer[bsize];
+	char buffer[bsize];
 	unsigned long long freemem = 0, buffers = 0, cache = 0;
-        *mem_tot = 0;
-        *mem_free = 0;
+	*mem_tot = 0;
+	*mem_free = 0;
 
-        if((fp = fopen("/proc/meminfo", "r")) == NULL)
-                return 1;
+	if((fp = fopen("/proc/meminfo", "r")) == NULL)
+		return 1;
 
-        while(fgets(buffer, bsize, fp) != NULL)
-        {
-                if(!swap)
-                {
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		if(!swap)
+		{
 			find_match_ll(buffer, "MemTotal:", mem_tot);
 			find_match_ll(buffer, "MemFree:", &freemem);
 			find_match_ll(buffer, "Buffers:", &buffers);
 			find_match_ll(buffer, "Cached:", &cache);
-                }
-                else
-                {
+		}
+		else
+		{
 			find_match_ll(buffer, "SwapTotal:", mem_tot);
 			find_match_ll(buffer, "SwapFree:", mem_free);
-                }
-        }
-	if (!swap) {
+		}
+	}
+	if (!swap)
+	{
 		*mem_free = freemem + buffers + cache;
 	}
-        fclose(fp);
-        return 0;
+	fclose(fp);
+
+	/* Convert to bytes */
+	*mem_free *= 1000;
+	*mem_tot *= 1000;
+	return 0;
 }
 
 int xs_parse_distro(char *name)
@@ -387,9 +249,9 @@ int xs_parse_distro(char *name)
 			find_match_char(buffer, "ACCEPT_KEYWORDS", keywords);
 		/* cppcheck-suppress uninitvar */
 		if (strstr(keywords, "\"") == NULL)
-			snprintf(buffer, bsize, "Gentoo Linux (stable)");
+			g_snprintf(buffer, bsize, "Gentoo Linux (stable)");
 		else
-			snprintf(buffer, bsize, "Gentoo Linux %s", keywords);
+			g_snprintf(buffer, bsize, "Gentoo Linux %s", keywords);
 	}
 	else if((fp = fopen("/etc/redhat-release", "r")) != NULL)
 		fgets(buffer, bsize, fp);
@@ -404,7 +266,7 @@ int xs_parse_distro(char *name)
 	else if((fp = fopen("/etc/turbolinux-release", "r")) != NULL)
 		fgets(buffer, bsize, fp);
 	else if((fp = fopen("/etc/arch-release", "r")) != NULL)
-		snprintf(buffer, bsize, "ArchLinux");
+		g_snprintf(buffer, bsize, "ArchLinux");
 	else if((fp = fopen("/etc/lsb-release", "r")) != NULL)
 	{
 		char id[bsize], codename[bsize], release[bsize];
@@ -417,45 +279,22 @@ int xs_parse_distro(char *name)
 			find_match_char(buffer, "DISTRIB_CODENAME", codename);
 			find_match_char(buffer, "DISTRIB_RELEASE", release);
 		}
-		snprintf(buffer, bsize, "%s \"%s\" %s", id, codename, release);
+		g_snprintf(buffer, bsize, "%s \"%s\" %s", id, codename, release);
 	}
 	else if((fp = fopen("/etc/debian_version", "r")) != NULL)
 	{
 		char release[bsize];
 		fgets(release, bsize, fp);
-		snprintf(buffer, bsize, "Debian %s", release);
+		g_snprintf(buffer, bsize, "Debian %s", release);
 	}
 	else
-		snprintf(buffer, bsize, "Unknown Distro");
-	if(fp != NULL) fclose(fp);
+		g_snprintf(buffer, bsize, "Unknown Distro");
+	if(fp != NULL)
+		fclose(fp);
 	
 	pos=strchr(buffer, '\n');
-	if(pos != NULL) *pos = '\0';
+	if(pos != NULL)
+		*pos = '\0';
 	strcpy(name, buffer);
 	return 0;
 }
-
-int xs_parse_hwmon_chip(char *chip)
-{
-	if (!hwmon_chip_present())
-		return 1;
-#if 0
-	else
-		get_hwmon_chip_name(chip);
-#endif
-	return 0;
-}
-
-int xs_parse_hwmon_temp(char *temp, unsigned int *sensor)
-{
-	unsigned int value;
-	float celsius;
-
-	if (!hwmon_chip_present())
-		return 1;
-	else
-		get_hwmon_temp(&value, sensor);
-		celsius = (float)value;
-		snprintf(temp, bsize, "%.1fC", celsius/1000.0);
-	return 0;
-}
diff --git a/plugins/sysinfo/parse.h b/plugins/sysinfo/unix/parse.h
index 27aac7da..c7cb571e 100644
--- a/plugins/sysinfo/parse.h
+++ b/plugins/sysinfo/unix/parse.h
@@ -23,18 +23,13 @@
 #ifndef _PARSE_H_
 #define _PARSE_H_
 
-int xs_parse_cpu(char *model, char *vendor, double *freq, char *cache, unsigned int *count);
-int xs_parse_uptime(int *weeks, int *days, int *hours, int *minutes, int *seconds);
-int xs_parse_os(char *user, char *host, char *kernel);
+int xs_parse_cpu(char *model, char *vendor, double *freq);
+gint64 xs_parse_uptime(void);
 int xs_parse_sound(char *snd_card);
-int xs_parse_netdev(const char *device, unsigned long long *bytes_recv, unsigned long long *bytes_sent);
-int xs_parse_df(const char *mount_point, char *string);
 int xs_parse_meminfo(unsigned long long *mem_tot, unsigned long long *mem_free, int swap);
 int xs_parse_video(char *vid_card);
 int xs_parse_agpbridge(char *agp_bridge);
 int xs_parse_ether(char *ethernet_card);
 int xs_parse_distro(char *name);
-int xs_parse_hwmon_chip(char *chip);
-int xs_parse_hwmon_temp(char *temp, unsigned int *sensor);
 
 #endif
diff --git a/plugins/sysinfo/unix/pci.c b/plugins/sysinfo/unix/pci.c
new file mode 100644
index 00000000..71b085fe
--- /dev/null
+++ b/plugins/sysinfo/unix/pci.c
@@ -0,0 +1,169 @@
+/*
+ * pci.c - PCI functions for X-Sys
+ * Copyright (C) 1997-1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz> [PCI routines from lspci]
+ * Copyright (C) 2000 Tom Rini <trini@kernel.crashing.org> [XorgAutoConfig pci.c, based on lspci]
+ * Copyright (C) 2005, 2006 Tony Vroon
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <pci/pci.h>
+#include <glib.h>
+
+#include "sysinfo.h"
+
+static struct pci_filter filter;       /* Device filter */
+static struct pci_access *pacc;
+int bus, dev, func; /* Location of the card */
+
+struct device {
+	struct device *next;
+	struct pci_dev *dev;
+	unsigned int config_cnt;
+	u8 config[256];
+};
+
+static struct device *first_dev;
+
+static struct device *scan_device(struct pci_dev *p)
+{
+	int how_much = 64;
+	struct device *d;
+
+	if (!pci_filter_match(&filter, p))
+		return NULL;
+	d = g_new0 (struct device, 1);
+	d->dev = p;
+	if (!pci_read_block(p, 0, d->config, how_much))
+		exit(1);
+	if (how_much < 128 && (d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
+	{
+		/* For cardbus bridges, we need to fetch 64 bytes more to get the full standard header... */
+		if (!pci_read_block(p, 64, d->config+64, 64))
+			exit(1);
+		how_much = 128;
+	}
+	d->config_cnt = how_much;
+	pci_setup_cache(p, d->config, d->config_cnt);
+	pci_fill_info(p, PCI_FILL_IDENT);
+	return d;
+}
+
+static void scan_devices(void)
+{
+	struct device *d;
+	struct pci_dev *p;
+
+	pci_scan_bus(pacc);
+	for(p=pacc->devices; p; p=p->next)
+	{
+		if ((d = scan_device(p)))
+		{
+			d->next = first_dev;
+			first_dev = d;
+		}
+	}
+}
+
+static u16 get_conf_word(struct device *d, unsigned int pos)
+{
+	  return d->config[pos] | (d->config[pos+1] << 8);
+}
+
+int pci_find_by_class(u16 *class, char *vendor, char *device)
+{
+	struct device *d;
+	struct pci_dev *p;
+	int nomatch = 1;
+
+	pacc = pci_alloc();
+	pci_filter_init(pacc, &filter);
+	pci_init(pacc);
+	scan_devices();
+
+	for(d=first_dev; d; d=d->next)
+	{
+		p = d->dev;
+		/* Acquire vendor & device ID if the class matches */
+		if(get_conf_word(d, PCI_CLASS_DEVICE) == *class)
+		{
+			nomatch = 0;
+			g_snprintf(vendor,7,"%04x",p->vendor_id);
+			g_snprintf(device,7,"%04x",p->device_id);
+			break;
+		}
+	  }
+
+	  pci_cleanup(pacc);
+	  return nomatch;
+}
+
+void pci_find_fullname(char *fullname, char *vendor, char *device)
+{
+	char buffer[bsize];
+	char vendorname[bsize/2] = "";
+	char devicename[bsize/2] = "";
+	char *position;
+	int cardfound = 0;
+	FILE *fp;
+	
+	if (!sysinfo_get_str_pref ("pciids", buffer))
+		strcpy (buffer, DEFAULT_PCIIDS);
+
+	fp = fopen (buffer, "r");
+	if(fp == NULL)
+	{
+		g_snprintf(fullname, bsize, "%s:%s", vendor, device);
+		//sysinfo_print_error ("pci.ids file not found! You might want to adjust your pciids setting with /SYSINFO SET pciids (you can query its current value with /SYSINFO LIST).\n");
+		return;
+	}
+
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		if (!isspace(buffer[0]) && strstr(buffer, vendor) != NULL)
+		{
+			position = strstr(buffer, vendor);
+			position += 6;
+			strncpy(vendorname, position, bsize/2);
+			position = strstr(vendorname, "\n");
+			*(position) = '\0';
+			break;
+		}
+	}
+	while(fgets(buffer, bsize, fp) != NULL)
+	{
+		if(strstr(buffer, device) != NULL)
+		{
+			position = strstr(buffer, device);
+			position += 6;
+			strncpy(devicename, position, bsize/2);
+			position = strstr(devicename, " (");
+			if (position == NULL)
+				position = strstr(devicename, "\n");
+			*(position) = '\0';
+			cardfound = 1;
+			break;
+		 }
+	}
+	if (cardfound == 1)
+		g_snprintf(fullname, bsize, "%s %s", vendorname, devicename);
+	else
+		g_snprintf(fullname, bsize, "%s:%s", vendor, device);	
+	fclose(fp);
+}
diff --git a/plugins/sysinfo/pci.h b/plugins/sysinfo/unix/pci.h
index 673f0a0a..673f0a0a 100644
--- a/plugins/sysinfo/pci.h
+++ b/plugins/sysinfo/unix/pci.h
diff --git a/plugins/sysinfo/win32/backend.c b/plugins/sysinfo/win32/backend.c
new file mode 100644
index 00000000..2451c122
--- /dev/null
+++ b/plugins/sysinfo/win32/backend.c
@@ -0,0 +1,493 @@
+/* HexChat
+ * Copyright (c) 2011-2012 Berke Viktor.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <windows.h>
+#include <wbemidl.h>
+
+#include <glib.h>
+
+#include "../format.h"
+
+/* Cache the info for subsequent invocations of /SYSINFO */
+static int cpu_arch = 0;
+static char *os_name = NULL;
+static char *cpu_info = NULL;
+static char *vga_name = NULL;
+
+static int command_callback (char *word[], char *word_eol[], void *user_data);
+
+typedef enum
+{
+	QUERY_WMI_OS,
+	QUERY_WMI_CPU,
+	QUERY_WMI_VGA,
+	QUERY_WMI_HDD,
+} QueryWmiType;
+
+void print_info (void);
+int get_cpu_arch (void);
+char *query_wmi (QueryWmiType mode);
+char *read_os_name (IWbemClassObject *object);
+char *read_cpu_info (IWbemClassObject *object);
+char *read_vga_name (IWbemClassObject *object);
+
+guint64 hdd_capacity;
+guint64 hdd_free_space;
+char *read_hdd_info (IWbemClassObject *object);
+
+char *get_memory_info (void);
+char *bstr_to_utf8 (BSTR bstr);
+guint64 variant_to_uint64 (VARIANT *variant);
+
+char *
+sysinfo_backend_get_sound (void)
+{
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_network (void)
+{
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_uptime (void)
+{
+	return sysinfo_format_uptime (GetTickCount64 () / 1000);
+}
+
+char *
+sysinfo_backend_get_disk (void)
+{
+	char *hdd_info;
+
+	/* HDD information is always loaded dynamically since it includes the current amount of free space */
+	hdd_capacity = 0;
+	hdd_free_space = 0;
+	hdd_info = query_wmi (QUERY_WMI_HDD);
+	if (hdd_info)
+		return sysinfo_format_disk (hdd_capacity, hdd_free_space);
+
+	return NULL;
+}
+
+char *
+sysinfo_backend_get_cpu (void)
+{
+	if (cpu_info == NULL)
+		cpu_info = query_wmi (QUERY_WMI_CPU);
+
+	return g_strdup (cpu_info);
+}
+
+char *
+sysinfo_backend_get_memory (void)
+{
+	/* Memory information is always loaded dynamically since it includes the current amount of free memory */
+	return get_memory_info ();
+}
+
+char *
+sysinfo_backend_get_gpu (void)
+{
+	if (vga_name == NULL)
+		vga_name = query_wmi (QUERY_WMI_VGA);
+
+	return g_strdup (vga_name);
+}
+
+char *
+sysinfo_backend_get_os (void)
+{
+	if (os_name == NULL)
+		os_name = query_wmi (QUERY_WMI_OS);
+
+	if (cpu_arch == 0)
+		cpu_arch = get_cpu_arch ();
+
+	return g_strdup_printf ("%s (x%d)", os_name, cpu_arch);
+}
+
+static int get_cpu_arch (void)
+{
+	SYSTEM_INFO si;
+
+	GetNativeSystemInfo (&si);
+
+	if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+	{
+		return 64;
+	}
+	else
+	{
+		return 86;
+	}
+}
+
+/* http://msdn.microsoft.com/en-us/site/aa390423 */
+static char *query_wmi (QueryWmiType type)
+{
+	GString *result = NULL;
+	HRESULT hr;
+
+	IWbemLocator *locator = NULL;
+	BSTR namespaceName = NULL;
+	BSTR queryLanguageName = NULL;
+	BSTR query = NULL;
+	IWbemServices *namespace = NULL;
+	IUnknown *namespaceUnknown = NULL;
+	IEnumWbemClassObject *enumerator = NULL;
+	int i;
+	gboolean atleast_one_appended = FALSE;
+
+	hr = CoCreateInstance (&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &locator);
+	if (FAILED (hr))
+	{
+		goto exit;
+	}
+
+	namespaceName = SysAllocString (L"root\\CIMV2");
+
+	hr = locator->lpVtbl->ConnectServer (locator, namespaceName, NULL, NULL, NULL, 0, NULL, NULL, &namespace);
+	if (FAILED (hr))
+	{
+		goto release_locator;
+	}
+
+	hr = namespace->lpVtbl->QueryInterface (namespace, &IID_IUnknown, &namespaceUnknown);
+	if (FAILED (hr))
+	{
+		goto release_namespace;
+	}
+
+	hr = CoSetProxyBlanket (namespaceUnknown, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
+	if (FAILED (hr))
+	{
+		goto release_namespaceUnknown;
+	}
+
+	queryLanguageName = SysAllocString (L"WQL");
+
+	switch (type)
+	{
+	case QUERY_WMI_OS:
+		query = SysAllocString (L"SELECT Caption FROM Win32_OperatingSystem");
+		break;
+	case QUERY_WMI_CPU:
+		query = SysAllocString (L"SELECT Name, MaxClockSpeed FROM Win32_Processor");
+		break;
+	case QUERY_WMI_VGA:
+		query = SysAllocString (L"SELECT Name FROM Win32_VideoController");
+		break;
+	case QUERY_WMI_HDD:
+		query = SysAllocString (L"SELECT Name, Capacity, FreeSpace FROM Win32_Volume");
+		break;
+	default:
+		goto release_queryLanguageName;
+	}
+
+	hr = namespace->lpVtbl->ExecQuery (namespace, queryLanguageName, query, WBEM_FLAG_FORWARD_ONLY, NULL, &enumerator);
+	if (FAILED (hr))
+	{
+		goto release_query;
+	}
+
+	result = g_string_new ("");
+
+	for (i = 0;; i++)
+	{
+		ULONG numReturned = 0;
+		IWbemClassObject *object;
+		char *line;
+
+		hr = enumerator->lpVtbl->Next (enumerator, WBEM_INFINITE, 1, &object, &numReturned);
+		if (FAILED (hr) || numReturned == 0)
+		{
+			break;
+		}
+
+		switch (type)
+		{
+			case QUERY_WMI_OS:
+				line = read_os_name (object);
+				break;
+
+			case QUERY_WMI_CPU:
+				line = read_cpu_info (object);
+				break;
+
+			case QUERY_WMI_VGA:
+				line = read_vga_name (object);
+				break;
+
+			case QUERY_WMI_HDD:
+				line = read_hdd_info (object);
+				break;
+
+			default:
+				break;
+		}
+
+		object->lpVtbl->Release (object);
+
+		if (line != NULL)
+		{
+			if (atleast_one_appended)
+			{
+				g_string_append (result, ", ");
+			}
+
+			g_string_append (result, line);
+
+			g_free (line);
+
+			atleast_one_appended = TRUE;
+		}
+	}
+
+	enumerator->lpVtbl->Release (enumerator);
+
+release_query:
+	SysFreeString (query);
+
+release_queryLanguageName:
+	SysFreeString (queryLanguageName);
+
+release_namespaceUnknown:
+	namespaceUnknown->lpVtbl->Release (namespaceUnknown);
+
+release_namespace:
+	namespace->lpVtbl->Release (namespace);
+
+release_locator:
+	locator->lpVtbl->Release (locator);
+	SysFreeString (namespaceName);
+
+exit:
+	if (result == NULL)
+	{
+		return NULL;
+	}
+
+	return g_string_free (result, FALSE);
+}
+
+static char *read_os_name (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT caption_variant;
+	char *caption_utf8;
+
+	hr = object->lpVtbl->Get (object, L"Caption", 0, &caption_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	caption_utf8 = bstr_to_utf8 (caption_variant.bstrVal);
+
+	VariantClear(&caption_variant);
+
+	if (caption_utf8 == NULL)
+	{
+		return NULL;
+	}
+
+	g_strchomp (caption_utf8);
+
+	return caption_utf8;
+}
+
+static char *read_cpu_info (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT name_variant;
+	char *name_utf8;
+	VARIANT max_clock_speed_variant;
+	guint cpu_freq_mhz;
+	char *result;
+
+	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	name_utf8 = bstr_to_utf8 (name_variant.bstrVal);
+
+	VariantClear (&name_variant);
+
+	if (name_utf8 == NULL)
+	{
+		return NULL;
+	}
+
+	hr = object->lpVtbl->Get (object, L"MaxClockSpeed", 0, &max_clock_speed_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		g_free (name_utf8);
+
+		return NULL;
+	}
+
+	cpu_freq_mhz = max_clock_speed_variant.uintVal;
+
+	VariantClear (&max_clock_speed_variant);
+
+	if (cpu_freq_mhz > 1000)
+	{
+		result = g_strdup_printf ("%s (%.2fGHz)", name_utf8, cpu_freq_mhz / 1000.f);
+	}
+	else
+	{
+		result = g_strdup_printf ("%s (%" G_GUINT32_FORMAT "MHz)", name_utf8, cpu_freq_mhz);
+	}
+
+	g_free (name_utf8);
+
+	return result;
+}
+
+static char *read_vga_name (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT name_variant;
+	char *name_utf8;
+
+	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	name_utf8 = bstr_to_utf8 (name_variant.bstrVal);
+
+	VariantClear (&name_variant);
+
+	if (name_utf8 == NULL)
+	{
+		return NULL;
+	}
+
+	return g_strchomp (name_utf8);
+}
+
+static char *read_hdd_info (IWbemClassObject *object)
+{
+	HRESULT hr;
+	VARIANT name_variant;
+	BSTR name_bstr;
+	gsize name_len;
+	VARIANT capacity_variant;
+	guint64 capacity;
+	VARIANT free_space_variant;
+	guint64 free_space;
+
+	hr = object->lpVtbl->Get (object, L"Name", 0, &name_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	name_bstr = name_variant.bstrVal;
+	name_len = SysStringLen (name_variant.bstrVal);
+
+	if (name_len >= 4 && name_bstr[0] == L'\\' && name_bstr[1] == L'\\' && name_bstr[2] == L'?' && name_bstr[3] == L'\\')
+	{
+		// This is not a named volume. Skip it.
+		VariantClear (&name_variant);
+
+		return NULL;
+	}
+
+	VariantClear (&name_variant);
+
+	hr = object->lpVtbl->Get (object, L"Capacity", 0, &capacity_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	capacity = variant_to_uint64 (&capacity_variant);
+
+	VariantClear (&capacity_variant);
+
+	if (capacity == 0)
+	{
+		return NULL;
+	}
+
+	hr = object->lpVtbl->Get (object, L"FreeSpace", 0, &free_space_variant, NULL, NULL);
+	if (FAILED (hr))
+	{
+		return NULL;
+	}
+
+	free_space = variant_to_uint64 (&free_space_variant);
+
+	VariantClear (&free_space_variant);
+
+	if (free_space == 0)
+	{
+		return NULL;
+	}
+
+	hdd_capacity += capacity;
+	hdd_free_space += free_space;
+
+	return NULL;
+}
+
+static char *get_memory_info (void)
+{
+	MEMORYSTATUSEX meminfo = { 0 };
+	meminfo.dwLength = sizeof (meminfo);
+
+	if (!GlobalMemoryStatusEx (&meminfo))
+	{
+		return NULL;
+	}
+
+	return sysinfo_format_memory (meminfo.ullTotalPhys, meminfo.ullAvailPhys);
+}
+
+static char *bstr_to_utf8 (BSTR bstr)
+{
+	return g_utf16_to_utf8 (bstr, SysStringLen (bstr), NULL, NULL, NULL);
+}
+
+static guint64 variant_to_uint64 (VARIANT *variant)
+{
+	switch (V_VT (variant))
+	{
+	case VT_UI8:
+		return variant->ullVal;
+
+	case VT_BSTR:
+		return wcstoull (variant->bstrVal, NULL, 10);
+
+	default:
+		return 0;
+	}
+}
diff --git a/plugins/sysinfo/xsys-changelog b/plugins/sysinfo/xsys-changelog
deleted file mode 100644
index 9ea20727..00000000
--- a/plugins/sysinfo/xsys-changelog
+++ /dev/null
@@ -1,116 +0,0 @@
-v2.2.0
-	* (Thomas Cort) Report L2 cache info for Alpha CPUs
-	* (Tony Vroon) Drop XMMS, port audacious features to D-Bus, make dependency mandatory
-	* (Tony Vroon) Use pretty_freespace for memory & swap reporting as well as disk space
-	* (Tony Vroon) Make pretty_freespace report none if total_size is 0, thanks to Emopig <andrew@nelless.net> for the report
-	* (Tony Vroon) Make pretty_freespace aware of terabytes, petabytes, exabytes, zettabytes & yottabytes
-	* (Tony Vroon) Remove xchatdirfs workaround
-
-v2.1.0
-	Removals & pending removal:
-	* (Tony Vroon) Remove support for BMP, it is an abandoned project. Suggested upgrade path: audacious
-	* (Tony Vroon) Remove /uname & /euname; the OS part of sysinfo displays similar info without requiring a process pipe
-	* (Tony Vroon) Added a note that the xchatdirfs workaround is due for removal as X-Chat Gnome has fixed the bug
-
-	Bugfixes:
-	* (Tony Vroon) Actually show the vendor that we retrieve in cpuinfo
-	* (Tony Vroon) Display Gentoo Linux as stable or ~arch, the baselayout version doesn't really interest anyone
-	* (Tony Vroon) Match framework: Make remove_leading_whitespace actually work
-	* (Tony Vroon) Match framework: Do not assume that a delimiter is always followed by a space
-
-	Code improvements:
-	* (Tony Vroon) PCI framework: We were requesting more info then we actually return to the caller
-	* (Tony Vroon) Match framework: Consolidate delimiters in a single define & use 1 strpbrk instead of 2 strstr's
-	* (Tony Vroon) Display the machine string instead of the pmac-generation as vendor info for PPC machines
-
-	New features
-	* (Tony Vroon) Show memory capacity in gigabytes instead of in megabytes when appropriate
-	* (Tony Vroon) Cut cpu name at comma (so overly long other info such as "altivec supported" is no longer displayed)
-	* (Tony Vroon) Now Playing: Report time played as well as the song length
-	* (Tony Vroon) Now Playing: Support reporting as an action; configurable at runtime
-	* (Tony Vroon) Check LSB release data, prefer above all others; based on a code sample submitted by Thomas Winwood
-
-v2.0.9
-	* (Tony Vroon) Protect the matching framework against spurious matches (bug reported by Harm Geerts)
-	* (Tony Vroon) Unexporting unnecessary symbols for PCI framework
-	* (Tony Vroon) Deal with incompatible header changes in pciutils
-	* (Tony Vroon) Begin implementing hardware monitoring support, not yet activated
-	* (Tony Vroon) Add support for Audacious, a BMP fork
-
-v2.0.8
-	* (Tony Vroon) Make XMMS interface actually work, thanks to a patch from Morten Cools
-	* (Tony Vroon) Use percentages for df information as well
-	* (Gustavo Zacarias) Add support for Sparc architecture, cache size detection on sparc64 only
-	* (Gustavo Zacarias) Consolidate buffer sizes into a single define
-
-v2.0.7
-	* (Tony Vroon) Have df parser ignore pseudo-filesystems; deal with other locales more gracefully
-	* (Tony Vroon) Change default formatstring not to use mIRC color codes
-	* (Tony Vroon) Add fallback to ~/.xchat2 for xchat-gnome which does not report xchatdirfs properly
-	* (Tony Vroon) Revert to beepctrl.h style calls as infopipe is too unreliable
-
-v2.0.6
-	* (Tony Vroon) Rewrote PCI framework, no longer depends on sysfs, kernel 2.4 and lower will work now
-	* (Tony Vroon) Made percentages configurable, can be set at runtime (feature request by Halcy0n)
-	* (Tony Vroon) Abstract out all pointer voodoo from xsys.c
-	* (Tony Vroon) Do not return XCHAT_EAT_NONE, causes spurious "unknown command" errors
-	* (Tony Vroon) Deal more gracefully with a missing soundcard or unknown linux distribution
-	* (Tony Vroon) Add error handling to the matching framework
-
-v2.0.5
-	* (Tony Vroon) Added support for parisc/hppa & ia64 architectures
-	* (Tony Vroon) Proper report of L2 cache as "unknown" instead of showing bits of unitialized memory
-	* (Tony Vroon) Upped PCI parser yield for ppc64 architecture, has high bus number for AGP card
-	* (Tony Vroon) Use percentages in memory/swap information
-
-v2.0.4
-	* (Tony Vroon) /sound uses ALSA if possible, PCI now fallback (false positives reported with PCI code)
-	* (Tony Vroon) Remove 0 prefix from first ALSA card; 1: and up will be shown for extra cards
-	* (Tony Vroon) Matching code rewritten and separated out from other code
-	* (Tony Vroon) Use new matching framework where possible
-	* (Tony Vroon) Added support for Alpha architecture, thanks to Bert (bert@ev6.net)
-
-v2.0.3
-	* (Tony Vroon) Fix buttons, XMMS -> NP
-	* (Tony Vroon) PCI functions separated out from other code; fully rewritten
-	* (Tony Vroon) Use new PCI framework for sound detection; ALSA is now fallback
-	* (Tony Vroon) Implement /ether
-	* (Tony Vroon) /video now reports video card @ AGP bridge; resolution info dropped
-
-v2.0.2
-	* (Tony Vroon) XMMS/BMP: Delete XMMS/BMP detection; it just got obsoleted by a BMP bugfix
-	* (Tony Vroon) XMMS/BMP: Change to /np & /enp as commands (np -> now playing)
-	* (Tony Vroon) Allow customization of now_playing with /playing
-	* (Tony Vroon) Separate out the length field for now_playing
-	* (Tony Vroon) Better configuration file handling
-	* (Tony Vroon) Set homepage to http://dev.gentoo.org/~chainsaw/xsys
-	* (Tony Vroon) Make channel buttons optional, not everyone appreciates them
-	* (Tony Vroon) Fix cpuinfo parsing on x86_64, a necessary define was missing
-
-v2.0.1
-	* (Tony Vroon) XMMS/BMP: Report "stream" if song length is -1
-	* (Tony Vroon) XMMS/BMP: Determine whether XMMS or BMP is playing
-	* (Tony Vroon) Better errorhandling if pci.ids parsing fails; at least mention raw PCI ID of card
-	* (Tony Vroon) Remove AGP from video card messages; we detect plain PCI cards too
-	* (Tony Vroon) Fix Debian release detector
-
-v2.0.0
-	* (mikeshoup)  Clean up of code for 2.0.0 release
-	* (Tony Vroon) Added PowerPC /proc/cpuinfo support
-	* (Tony Vroon) Changed LSPCI to SYSFS
-
-v1.9.3
-	* (mikeshoup) Introduced distro function
-	* (mikeshoup, Tony Vroon's suggestion) Removed bitrate from /XMMS
-
-v1.9.2
-	* 2005/01/14 (mikeshoup) Put in the userlist buttons
-	* 2005/01/10 (mikeshoup) Added XMMS/BMP Support
-
-v1.9.1
-	* 2004/12/20 (mikeshoup) Added a dynamic formatting scheme
-	* 2004/12/19 (mikeshoup) Changed some commands
-	* 2004/12/18 (mikeshoup) Reintroducted /VIDEO
-
-v1.9.0
-	* 2004/12/17 (mikeshoup) Initial Release
diff --git a/plugins/sysinfo/xsys-install b/plugins/sysinfo/xsys-install
deleted file mode 100644
index 8f148569..00000000
--- a/plugins/sysinfo/xsys-install
+++ /dev/null
@@ -1,15 +0,0 @@
-INSTALLATION
-============
-Installation is straightforward. You need Audacious 1.4 or higher and D-Bus.
-Open up the Makefile, check to make sure PCIIDS points to your pci.ids file.
-	(Symptom if you get it wrong: raw PCI ID's (XXXX:XXXX) emitted by /VIDEO and friends).
-
-Run: make
-Run: make install
-
-Voila!
-
-NOTES:
-`make install' copies the compiled library (something like xsys-v.v.v.so) to
-$HOME/.xchat2/xsys-plugin.so for autoloading. If $HOME/.xchat2/xsys-plugin.so
-exists, it is removed first.
diff --git a/plugins/sysinfo/xsys-makefile b/plugins/sysinfo/xsys-makefile
deleted file mode 100644
index 8b51a53d..00000000
--- a/plugins/sysinfo/xsys-makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-#### SET THIS VALUE TO THE LOCATION OF THE `pci.ids` file ####
-PCIIDS = /usr/share/misc/pci.ids
-
-#### UNCOMMENT THIS IF YOU WANT THE BUTTONS ####
-#BUTTON = -Dbuttonbar
-
-#### SHOULD NOT NEED TO EDIT BELOW THIS LINE ####
-VER_MAJOR = 2
-VER_MINOR = 2
-VER_PATCH = 0
-CC = gcc
-CFLAGS += -O2 -Wall -fPIC
-CFLAGS += -DVER_MINOR=$(VER_MINOR) -DVER_MAJOR=$(VER_MAJOR) -DVER_PATCH=$(VER_PATCH) \
-          -DVER_STRING=\"$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH)\" -DPCIIDS=\"$(PCIIDS)\" $(BUTTON)
-LDFLAGS = $(CFLAGS) -shared
-LIBRARY = xsys-$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH).so
-OBJECTS = xsys.o parse.o pci.o match.o hwmon.o
-
-ALL : $(LIBRARY)
-
-$(LIBRARY) : $(OBJECTS)
-	$(CC) $(LDFLAGS) -o $(LIBRARY) $(OBJECTS) -lpci
-
-xsys.o : xsys.c
-parse.o : parse.c
-pci.o : pci.c
-match.o : match.c
-hwmon.o : hwmon.c
-
-.PHONY : clean
-clean :
-	rm -rf *.o *.so *~
-
-.PHONY : install
-install : $(LIBRARY)
-	rm -f $(HOME)/.xchat2/xsys-plugin.so
-	cp ./$(LIBRARY) $(HOME)/.xchat2/xsys-plugin.so
-
diff --git a/plugins/sysinfo/xsys-readme b/plugins/sysinfo/xsys-readme
deleted file mode 100644
index 6226e725..00000000
--- a/plugins/sysinfo/xsys-readme
+++ /dev/null
@@ -1,105 +0,0 @@
-X-Sys README
-============
-What is X-Sys?
-
-X-Sys is a plugin for X-Chat that allows you to display your current system statistics in
-a channel, private conversation or just in an echo to yourself for testing purposes.
-It is supported on Linux, running on various architectures. Right now x86, ppc, ppc64, sparc,
-sparc64 and alpha are supported, with parisc and ia64 implemented but awaiting testing.
-
----------------
-Who wrote this?
-
-X-Sys is originally a Mike Shoup creation, from the very first alpha releases to the open-source
-version 1 releases. But then, things stalled. For a few months (more like a year almost)
-Mike didn't work on X-Sys. The last version that had been written was 1.0.5.
-The website was gone, and I (Tony) couldn't find Mike. So, I took over and improved it to my liking. 
-It turned out that Mike was still around, though, he contacted me and started development again,
-now called version 2, a complete rewrite. Various 1.9 betas came out that I contributed patches to,
-and starting with version 2.0.0 I'm maintaining xchat-xsys again, this time with Mike's blessing.
-
----------------
-What do I need?
-
-- X-Chat (regular or Gnome version)
-- Audacious 1.4 or higher
-- D-Bus (for communication with Audacious)
-- a working toolchain (compiler, binutils, etc).
-
-------------------------------------------------
-What if I get errors about u8 not being defined?
-
-Sorry to hear that, it appears your linux distribution neglected to install essential headers on your 
-system. On Debian & Ubuntu, apt-get install pciutils-dev should make it happy.
-
-========
-COMMANDS
-
-X-Sys 2 has the following implemented commands:
-/XSYS & /EXSYS - Output current version, either to channel or echoed on screen.
-/CPUINFO & /ECPUINFO - Echoes or says current cpu statistics
-/SYSUPTIME & /ESYSUPTIME - Echoes or says current uptime
-/OSINFO & /EOSINFO - Echoes or says various OS statistics
-/SOUND & /ESOUND - Echoes or says the current sound card, as determined by ALSA
-/NETDATA & /ENETDATA - Echoes or says total amount transferred through a network
-	interface. Use like: `/netdata eth0' (where eth0 is a network interface)
-/NETSTREAM & /ENETSTREAM - Echoes or says amount of bandwidth being used.
-	Use like: `/netstream eth0' (where eth0 is a network interface)
-/DISKINFO & /EDISKINFO - Echoes or says free space on partitions. The DISK command has a
-	few arguments as follows:
-	ALL - Displays every partitions
-	/mount - Displays free space for that specific mount point
-	No arguments just displays total free space
-/MEMINFO & /EMEMINFO - Echoes or says memory information.
-/VIDEO & /EVIDEO - Echoes or says the current video card on the PCI bus
-/ETHER & /EETHER - Echoes or says the current network card on the PCI bus
-/DISTRO & /EDISTRO - Echoes or says which distro you're running
-	If this doesn't work for your distro, look for a *-release file or similar in /etc
-	E-mail this to chainsaw@gentoo.org
-
-and the big one:
-/SYSINFO & /ESYSINFO - Complete system information!
-
-Two output control commands:
-/XSYS2FORMAT , No arguments, it will print just the current formatting string.
-   It will take any arguments to it as the formatting string.
-   The formatting string can consist of any letter/numbers, and is used to format
-   the output. The following special symbols can be used:
-   
-   %B      : Bold
-   %Cnn    : Foreground Color, where nn is a number corresponding to a mIRC color
-   %Cnn,nn : Foreground,Background Color
-   %R      : Reverse Foreground/Background Colors
-   %O      : Reset Color and Format (thats an 'oh' not a 'zero (0)')
-   %C      : Reset Color
-   %U      : Underline 
-
-/PLAYING will either print or allow you to set the text for /np.
-The default is now_playing, but you can set this to whatever text you prefer.
-
-/PERCENTAGES will allow you to set whether to use percentages in plugin output or not.
-Percentages are enabled  by default. Use a zero value to disable, and a non-zero value
-to enable. If unsure, use 1.
-
-/NP & /ENP - Reports what's currently playing in Audacious.
-
-====
-BUGS
-(none known)
-
-E-mail me your bug reports at chainsaw@gentoo.org
-Please include the following information:
-- what architecture you are using (amd64, ia64, parisc, ppc, ppc64, sparc, sparc64 or x86)
-- what linux distribution you are using (Gentoo 2007.1, Fedora Core 8, etc)
-- what compiler you have used to compile X-Sys, i.e. gcc (GCC) 4.1.2 (Gentoo 4.1.2)
-- what version of X-Sys you are using
-
-=======
-Thanks!
-Remember, everything here is:
-(C) 2003, 2004, 2005 by Michael Shoup
-(C) 2005, 2006, 2007 by Tony Vroon
-All Rights Reserved.
-Visit http://dev.gentoo.org/~chainsaw/xsys/ for release information.
-
-Feel free to e-mail me for feature requests, or see if I'm online on irc.freenode.net
diff --git a/plugins/sysinfo/xsys.c b/plugins/sysinfo/xsys.c
deleted file mode 100644
index 4ab6e873..00000000
--- a/plugins/sysinfo/xsys.c
+++ /dev/null
@@ -1,923 +0,0 @@
-/*
- * SysInfo - sysinfo plugin for HexChat
- * Copyright (c) 2012 Berke Viktor.
- *
- * xsys.c - main functions for X-Sys 2
- * by mikeshoup
- * Copyright (C) 2003, 2004, 2005 Michael Shoup
- * Copyright (C) 2005, 2006, 2007 Tony Vroon
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#include "hexchat-plugin.h"
-#include "parse.h"
-#include "match.h"
-#include "xsys.h"
-
-#define DEFAULT_FORMAT "%B%1:%B %2 **"
-#define DEFAULT_PERCENT 1
-#define DEFAULT_ANNOUNCE 1
-#define DEFAULT_PCIIDS "/usr/share/hwdata/pci.ids"
-
-static hexchat_plugin *ph;	/* plugin handle */
-static int error_printed = 0;	/* semaphore, make sure not to print the same error more than once during one execution */
-
-static char name[] = "SysInfo";
-static char desc[] = "Display info about your hardware and OS";
-static char version[] = "3.0";
-static char sysinfo_help[] = "SysInfo Usage:\n  /SYSINFO [-e|-o] [OS|DISTRO|CPU|RAM|DISK|VGA|SOUND|ETHERNET|UPTIME], print various details about your system or print a summary without arguments\n  /SYSINFO LIST, print current settings\n  /SYSINFO SET <variable>, update given setting\n  /SYSINFO RESET, reset settings to defaults\n  /NETDATA <iface>, show transmitted data on given interface\n  /NETSTREAM <iface>, show current bandwidth on given interface\n";
-
-void
-sysinfo_get_pciids (char* dest)
-{
-	hexchat_pluginpref_get_str (ph, "pciids", dest);
-}
-
-int
-sysinfo_get_percent ()
-{
-	return hexchat_pluginpref_get_int (ph, "percent");
-}
-
-int
-sysinfo_get_announce ()
-{
-	return hexchat_pluginpref_get_int (ph, "announce");
-}
-
-void
-sysinfo_print_error (const char* msg)
-{
-	if (!error_printed)
-	{
-		hexchat_printf (ph, "%s\t%s", name, msg);
-	}
-	error_printed++;
-	
-}
-
-static int
-print_summary (int announce, char* format)
-{
-	char sysinfo[bsize];
-	char buffer[bsize];
-	char cpu_model[bsize];
-	char cpu_cache[bsize];
-	char cpu_vendor[bsize];
-	char os_host[bsize];
-	char os_user[bsize];
-	char os_kernel[bsize];
-	unsigned long long mem_total;
-	unsigned long long mem_free;
-	unsigned int count;
-	double cpu_freq;
-	int giga = 0;
-	int weeks;
-	int days;
-	int hours;
-	int minutes;
-	int seconds;
-	sysinfo[0] = '\0';
-
-	snprintf (buffer, bsize, "%s", hexchat_get_info (ph, "version"));
-	format_output ("HexChat", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN OS PARSING */
-	if (xs_parse_os (os_user, os_host, os_kernel) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_os()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	snprintf (buffer, bsize, "%s", os_kernel);
-	format_output ("OS", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN DISTRO PARSING */
-        if (xs_parse_distro (buffer) != 0)
-        {
-		strncpy (buffer, "Unknown", bsize);
-	}
-
-	format_output ("Distro", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));	
-
-	/* BEGIN CPU PARSING */
-	if (xs_parse_cpu (cpu_model, cpu_vendor, &cpu_freq, cpu_cache, &count) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_cpu()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (cpu_freq > 1000)
-	{
-		cpu_freq /= 1000;
-		giga = 1;
-	}
-
-	if (giga)
-	{
-		snprintf (buffer, bsize, "%u x %s (%s) @ %.2fGHz", count, cpu_model, cpu_vendor, cpu_freq);
-	}
-	else
-	{
-		snprintf (buffer, bsize, "%u x %s (%s) @ %.0fMHz", count, cpu_model, cpu_vendor, cpu_freq);
-	}
-
-	format_output ("CPU", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN MEMORY PARSING */
-	if (xs_parse_meminfo (&mem_total, &mem_free, 0) == 1)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_meminfo!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	snprintf (buffer, bsize, "%s", pretty_freespace ("Physical", &mem_free, &mem_total));
-	format_output ("RAM", buffer, format);	
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (sysinfo));
-
-	/* BEGIN DISK PARSING */
-	if (xs_parse_df (NULL, buffer))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_df", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("Disk", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN VIDEO PARSING */
-	if (xs_parse_video (buffer))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_video", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("VGA", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN SOUND PARSING */
-	if (xs_parse_sound (buffer))
-	{
-		strncpy (buffer, "Not present", bsize);
-	}
-
-	format_output ("Sound", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN ETHERNET PARSING */
-	if (xs_parse_ether (buffer))
-	{
-		strncpy (buffer, "None found", bsize);
-	}
-
-	format_output ("Ethernet", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	/* BEGIN UPTIME PARSING */
-	if (xs_parse_uptime (&weeks, &days, &hours, &minutes, &seconds))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_uptime()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (minutes != 0 || hours != 0 || days != 0 || weeks != 0)
-	{
-		if (hours != 0 || days != 0 || weeks != 0)
-		{
-			if (days  !=0 || weeks != 0)
-			{
-				if (weeks != 0)
-				{
-					snprintf (buffer, bsize, "%dw %dd %dh %dm %ds", weeks, days, hours, minutes, seconds);
-				}
-				else
-				{
-					snprintf (buffer, bsize, "%dd %dh %dm %ds", days, hours, minutes, seconds);
-				}
-			}
-			else
-			{
-				snprintf (buffer, bsize, "%dh %dm %ds", hours, minutes, seconds);
-			}
-		}
-		else
-		{
-			snprintf (buffer, bsize, "%dm %ds", minutes, seconds);
-		}
-	}
-
-        format_output ("Uptime", buffer, format);
-	strcat (sysinfo, "\017 ");
-	strncat (sysinfo, buffer, bsize - strlen (buffer));
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", sysinfo);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", sysinfo);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_os (int announce, char* format)
-{
-	char buffer[bsize];
-	char user[bsize];
-	char host[bsize];
-	char kernel[bsize];
-
-	if (xs_parse_os (user, host, kernel) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_os()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	snprintf (buffer, bsize, "%s@%s, %s", user, host, kernel);
-	format_output ("OS", buffer, format);
-	
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_distro (int announce, char* format)
-{
-	char name[bsize];
-
-	if (xs_parse_distro (name) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_distro()!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output("Distro", name, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", name);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", name);
-	}
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_cpu (int announce, char* format)
-{
-	char model[bsize];
-	char vendor[bsize];
-	char cache[bsize];
-	char buffer[bsize];
-	unsigned int count;
-	double freq;
-	int giga = 0;
-
-	if (xs_parse_cpu (model, vendor, &freq, cache, &count) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_cpu()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (freq > 1000)
-	{
-		freq /= 1000;
-		giga = 1;
-	}
-
-	if (giga)
-	{
-		snprintf (buffer, bsize, "%u x %s (%s) @ %.2fGHz w/ %s L2 Cache", count, model, vendor, freq, cache);
-	}
-	else
-	{
-		snprintf (buffer, bsize, "%u x %s (%s) @ %.0fMHz w/ %s L2 Cache", count, model, vendor, freq, cache);
-	}
-
-	format_output ("CPU", buffer, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_ram (int announce, char* format)
-{
-	unsigned long long mem_total;
-	unsigned long long mem_free;
-	unsigned long long swap_total;
-	unsigned long long swap_free;
-	char string[bsize];
-
-	if (xs_parse_meminfo (&mem_total, &mem_free, 0) == 1)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_meminfo!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-	if (xs_parse_meminfo (&swap_total, &swap_free, 1) == 1)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_meminfo!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	snprintf (string, bsize, "%s - %s", pretty_freespace ("Physical", &mem_free, &mem_total), pretty_freespace ("Swap", &swap_free, &swap_total));
-	format_output ("RAM", string, format);
-	
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", string);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", string);
-	}
-	
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_disk (int announce, char* format)
-{
-	char string[bsize] = {0,};
-
-#if 0
-	if (*word == '\0')
-	{
-		if (xs_parse_df (NULL, string))
-		{
-			hexchat_printf (ph, "ERROR in parse_df");
-			return HEXCHAT_EAT_ALL;
-		}
-	}
-	else
-	{
-		if (xs_parse_df (*word, string))
-		{
-			hexchat_printf (ph, "ERROR in parse_df");
-			return HEXCHAT_EAT_ALL;
-		}
-	}
-#endif
-
-	if (xs_parse_df (NULL, string))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_df", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("Disk", string, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", string);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", string);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_vga (int announce, char* format)
-{
-	char vid_card[bsize];
-	char agp_bridge[bsize];
-	char buffer[bsize];
-	int ret;
-
-	if ((ret = xs_parse_video (vid_card)) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_video! %d", name, ret);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (xs_parse_agpbridge (agp_bridge) != 0)
-	{
-		snprintf (buffer, bsize, "%s", vid_card);
-	}
-	else
-	{
-		snprintf (buffer, bsize, "%s @ %s", vid_card, agp_bridge);
-	}
-
-	format_output ("VGA", buffer, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_sound (int announce, char* format)
-{
-	char sound[bsize];
-
-	if (xs_parse_sound (sound) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_asound()!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	format_output ("Sound", sound, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", sound);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", sound);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-
-static int
-print_ethernet (int announce, char* format)
-{
-	char ethernet_card[bsize];
-
-	if (xs_parse_ether (ethernet_card))
-	{
-		strncpy (ethernet_card, "None found", bsize);
-	}
-
-	format_output ("Ethernet", ethernet_card, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", ethernet_card);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", ethernet_card);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-print_uptime (int announce, char* format)
-{
-	char buffer[bsize];
-	int weeks;
-	int days;
-	int hours;
-	int minutes;
-	int seconds;
-
-	if (xs_parse_uptime (&weeks, &days, &hours, &minutes, &seconds))
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_uptime()", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (minutes != 0 || hours != 0 || days != 0 || weeks != 0)
-	{
-		if (hours != 0 || days != 0 || weeks != 0)
-		{
-			if (days  !=0 || weeks != 0)
-			{
-				if (weeks != 0)
-				{
-					snprintf (buffer, bsize, "%dw %dd %dh %dm %ds", weeks, days, hours, minutes, seconds);
-				}
-				else
-				{
-					snprintf (buffer, bsize, "%dd %dh %dm %ds", days, hours, minutes, seconds);
-				}
-			}
-			else
-			{
-				snprintf (buffer, bsize, "%dh %dm %ds", hours, minutes, seconds);
-			}
-		}
-		else
-		{
-			snprintf (buffer, bsize, "%dm %ds", minutes, seconds);
-		}
-	}
-
-	format_output ("Uptime", buffer, format);
-
-	if (announce)
-	{
-		hexchat_commandf (ph, "SAY %s", buffer);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", buffer);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-netdata_cb (char *word[], char *word_eol[], void *userdata)
-{
-	char netdata[bsize];
-	char format[bsize];
-	unsigned long long bytes_recv;
-	unsigned long long bytes_sent;
-	
-	if (*word[2] == '\0')
-	{
-		hexchat_printf (ph, "%s\tYou must specify a network device (e.g. /NETDATA eth0)!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (xs_parse_netdev (word[2], &bytes_recv, &bytes_sent) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_netdev", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	bytes_recv /= 1024;
-	bytes_sent /= 1024;
-	
-	snprintf (netdata, bsize, "%s: %.1f MB Received, %.1f MB Sent", word[2], (double)bytes_recv/1024.0, (double)bytes_sent/1024.0);
-	hexchat_pluginpref_get_str (ph, "format", format);
-	format_output ("Netdata", netdata, format);
-
-	if (hexchat_list_int (ph, NULL, "type") >= 2)
-	{
-		hexchat_commandf (ph, "SAY %s", netdata);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", netdata);
-	}
-	
-	return HEXCHAT_EAT_ALL;
-}
-
-static int
-netstream_cb (char *word[], char *word_eol[], void *userdata)
-{
-	char netstream[bsize];
-	char mag_r[5];
-	char mag_s[5];
-	char format[bsize];
-	unsigned long long bytes_recv;
-	unsigned long long bytes_sent;
-	unsigned long long bytes_recv_p;
-	unsigned long long bytes_sent_p;
-
-	struct timespec ts = {1, 0};
-
-	if (*word[2] == '\0')
-	{
-		hexchat_printf (ph, "%s\tYou must specify a network device (e.g. /NETSTREAM eth0)!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	if (xs_parse_netdev(word[2], &bytes_recv, &bytes_sent) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_netdev", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	while (nanosleep (&ts, &ts) < 0);
-
-	if (xs_parse_netdev(word[2], &bytes_recv_p, &bytes_sent_p) != 0)
-	{
-		hexchat_printf (ph, "%s\tERROR in parse_netdev", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	bytes_recv = (bytes_recv_p - bytes_recv);
-	bytes_sent = (bytes_sent_p - bytes_sent);
-
-	if (bytes_recv > 1024)
-	{
-		bytes_recv /= 1024;
-		snprintf (mag_r, 5, "KB/s");
-	}
-	else
-	{
-		snprintf (mag_r, 5, "B/s");
-	}
-
-	if (bytes_sent > 1024)
-	{
-		bytes_sent /= 1024;
-		snprintf (mag_s, 5, "KB/s");
-	}
-	else
-	{
-		snprintf (mag_s, 5, "B/s");
-	}
-
-	snprintf (netstream, bsize, "%s: Receiving %llu %s, Sending %llu %s", word[2], bytes_recv, mag_r, bytes_sent, mag_s);
-	hexchat_pluginpref_get_str (ph, "format", format);
-	format_output ("Netstream", netstream, format);
-
-	if (hexchat_list_int (ph, NULL, "type") >= 2)
-	{
-		hexchat_commandf (ph, "SAY %s", netstream);
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", netstream);
-	}
-
-	return HEXCHAT_EAT_ALL;
-}
-
-static void
-list_settings ()
-{
-	char list[512];
-	char buffer[512];
-	char* token;
-
-	hexchat_pluginpref_list (ph, list);
-	hexchat_printf (ph, "%s\tCurrent Settings:", name);
-	token = strtok (list, ",");
-
-	while (token != NULL)
-	{
-		hexchat_pluginpref_get_str (ph, token, buffer);
-		hexchat_printf (ph, "%s\t%s: %s\n", name, token, buffer);
-		token = strtok (NULL, ",");
-	}
-}
-
-static void
-reset_settings ()
-{
-	hexchat_pluginpref_set_str (ph, "pciids", DEFAULT_PCIIDS);
-	hexchat_pluginpref_set_str (ph, "format", DEFAULT_FORMAT);
-	hexchat_pluginpref_set_int (ph, "percent", DEFAULT_PERCENT);
-	hexchat_pluginpref_set_int (ph, "announce", DEFAULT_ANNOUNCE);
-}
-
-static int
-sysinfo_cb (char *word[], char *word_eol[], void *userdata)
-{
-	error_printed = 0;
-	int announce = sysinfo_get_announce ();
-	int offset = 0;
-	int buffer;
-	char format[bsize];
-
-	if (!hexchat_pluginpref_get_str (ph, "format", format))
-	{
-		hexchat_printf (ph, "%s\tError reading config file!", name);
-		return HEXCHAT_EAT_ALL;
-	}
-
-	/* Cannot send to server tab */
-	if (hexchat_list_int (ph, NULL, "type") == 1)
-	{
-		announce = 0;
-	}
-
-	/* Allow overriding global announce setting */
-	if (!strcmp ("-e", word[2]))
-	{
-		announce = 0;
-		offset++;
-	}
-	else if (!strcmp ("-o", word[2]))
-	{
-		announce = 1;
-		offset++;
-	}
-
-	if (!g_ascii_strcasecmp ("HELP", word[2+offset]))
-	{
-		hexchat_printf (ph, "%s", sysinfo_help);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("LIST", word[2+offset]))
-	{
-		list_settings ();
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("SET", word[2+offset]))
-	{
-		if (!g_ascii_strcasecmp ("", word_eol[4+offset]))
-		{
-			hexchat_printf (ph, "%s\tEnter a value!\n", name);
-			return HEXCHAT_EAT_ALL;
-		}
-		if (!g_ascii_strcasecmp ("format", word[3+offset]))
-		{
-			hexchat_pluginpref_set_str (ph, "format", word_eol[4+offset]);
-			hexchat_printf (ph, "%s\tformat is set to: %s\n", name, word_eol[4+offset]);
-		}
-		else if (!g_ascii_strcasecmp ("percent", word[3+offset]))
-		{
-			buffer = atoi (word[4+offset]);	/* don't use word_eol, numbers must not contain spaces */
-
-			if (buffer > 0 && buffer < INT_MAX)
-			{
-				hexchat_pluginpref_set_int (ph, "percent", buffer);
-				hexchat_printf (ph, "%s\tpercent is set to: %d\n", name, buffer);
-			}
-			else
-			{
-				hexchat_printf (ph, "%s\tInvalid input!\n", name);
-			}
-		}
-		else if (!g_ascii_strcasecmp ("announce", word[3+offset]))
-		{
-			buffer = atoi (word[4+offset]);	/* don't use word_eol, numbers must not contain spaces */
-
-			if (buffer > 0)
-			{
-				hexchat_pluginpref_set_int (ph, "announce", 1);
-				hexchat_printf (ph, "%s\tannounce is set to: On\n", name);
-			}
-			else
-			{
-				hexchat_pluginpref_set_int (ph, "announce", 0);
-				hexchat_printf (ph, "%s\tannounce is set to: Off\n", name);
-			}
-		}
-		else if (!g_ascii_strcasecmp ("pciids", word[3+offset]))
-		{
-			hexchat_pluginpref_set_str (ph, "pciids", word_eol[4+offset]);
-			hexchat_printf (ph, "%s\tpciids is set to: %s\n", name, word_eol[4+offset]);
-		}
-		else
-		{
-			hexchat_printf (ph, "%s\tInvalid variable name! Use 'pciids', 'format' or 'percent'!\n", name);
-			return HEXCHAT_EAT_ALL;
-		}
-
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("RESET", word[2+offset]))
-	{
-		reset_settings ();
-		hexchat_printf (ph, "%s\tSettings have been restored to defaults.\n", name);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("OS", word[2+offset]))
-	{
-		print_os (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("DISTRO", word[2+offset]))
-	{
-		print_distro (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("CPU", word[2+offset]))
-	{
-		print_cpu (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("RAM", word[2+offset]))
-	{
-		print_ram (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("DISK", word[2+offset]))
-	{
-		print_disk (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("VGA", word[2+offset]))
-	{
-		print_vga (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("SOUND", word[2+offset]))
-	{
-		print_sound (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("ETHERNET", word[2+offset]))
-	{
-		print_ethernet (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("UPTIME", word[2+offset]))
-	{
-		print_uptime (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else if (!g_ascii_strcasecmp ("", word[2+offset]))
-	{
-		print_summary (announce, format);
-		return HEXCHAT_EAT_ALL;
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", sysinfo_help);
-		return HEXCHAT_EAT_ALL;
-	}
-}
-
-int
-hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
-{
-	ph = plugin_handle;
-	*plugin_name    = name;
-	*plugin_desc    = desc;
-	*plugin_version = version;
-	char buffer[bsize];
-
-	hexchat_hook_command (ph, "SYSINFO",	HEXCHAT_PRI_NORM,	sysinfo_cb,	sysinfo_help, NULL);
-	hexchat_hook_command (ph, "NETDATA",	HEXCHAT_PRI_NORM,	netdata_cb,	NULL, NULL);
-	hexchat_hook_command (ph, "NETSTREAM",	HEXCHAT_PRI_NORM,	netstream_cb,	NULL, NULL);
-
-	/* this is required for the very first run */
-	if (hexchat_pluginpref_get_str (ph, "pciids", buffer) == 0)
-	{
-		hexchat_pluginpref_set_str (ph, "pciids", DEFAULT_PCIIDS);
-	}
-
-	if (hexchat_pluginpref_get_str (ph, "format", buffer) == 0)
-	{
-		hexchat_pluginpref_set_str (ph, "format", DEFAULT_FORMAT);
-	}
-
-	if (hexchat_pluginpref_get_int (ph, "percent") == -1)
-	{
-		hexchat_pluginpref_set_int (ph, "percent", DEFAULT_PERCENT);
-	}
-
-	if (hexchat_pluginpref_get_int (ph, "announce") == -1)
-	{
-		hexchat_pluginpref_set_int (ph, "announce", DEFAULT_ANNOUNCE);
-	}
-
-	hexchat_command (ph, "MENU ADD \"Window/Send System Info\" \"SYSINFO\"");
-	hexchat_printf (ph, "%s plugin loaded\n", name);
-	return 1;
-}
-
-int
-hexchat_plugin_deinit (void)
-{
-	hexchat_command (ph, "MENU DEL \"Window/Display System Info\"");
-	hexchat_printf (ph, "%s plugin unloaded\n", name);
-	return 1;
-}
diff --git a/plugins/upd/upd.c b/plugins/upd/upd.c
index 6fcf3be9..c9011c04 100644
--- a/plugins/upd/upd.c
+++ b/plugins/upd/upd.c
@@ -20,260 +20,50 @@
  * THE SOFTWARE.
  */
 
-#include <windows.h>
-#include <wininet.h>
-
-#include <glib.h>
+#include <winsparkle.h>
 
 #include "hexchat-plugin.h"
 
-#define DEFAULT_DELAY 30	/* 30 seconds */
-#define DEFAULT_FREQ 360	/* 6 hours */
-#define DOWNLOAD_URL "http://dl.hexchat.net/hexchat"
+#define APPCAST_URL "https://dl.hexchat.net/appcast.xml"
 
 static hexchat_plugin *ph;   /* plugin handle */
 static char name[] = "Update Checker";
 static char desc[] = "Check for HexChat updates automatically";
-static char version[] = "4.0";
-static const char upd_help[] = "Update Checker Usage:\n  /UPDCHK, check for HexChat updates\n  /UPDCHK SET delay|freq, set startup delay or check frequency\n";
-
-static char*
-check_version ()
-{
-	HINTERNET hOpen, hConnect, hResource;
-
-	hOpen = InternetOpen (TEXT ("Update Checker"),
-						INTERNET_OPEN_TYPE_PRECONFIG,
-						NULL,
-						NULL,
-						0);
-	if (!hOpen)
-	{
-		return "Unknown";
-	}
-
-	hConnect = InternetConnect (hOpen,
-								TEXT ("raw.github.com"),
-								INTERNET_DEFAULT_HTTPS_PORT,
-								NULL,
-								NULL,
-								INTERNET_SERVICE_HTTP,
-								0,
-								0);
-	if (!hConnect)
-	{
-		InternetCloseHandle (hOpen);
-		return "Unknown";
-	}
-
-	hResource = HttpOpenRequest (hConnect,
-								TEXT ("GET"),
-								TEXT ("/hexchat/hexchat/master/win32/version.txt"),
-								TEXT ("HTTP/1.0"),
-								NULL,
-								NULL,
-								INTERNET_FLAG_SECURE | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_AUTH,
-								0);
-	if (!hResource)
-	{
-		InternetCloseHandle (hConnect);
-		InternetCloseHandle (hOpen);
-		return "Unknown";
-	}
-	else
-	{
-		static char buffer[1024];
-		char infobuffer[32];
-		int statuscode;
-
-		DWORD dwRead;
-		DWORD infolen = sizeof(infobuffer);
-
-		HttpAddRequestHeaders (hResource, TEXT ("Connection: close\r\n"), -1L, HTTP_ADDREQ_FLAG_ADD);	/* workaround for GC bug */
-		HttpSendRequest (hResource, NULL, 0, NULL, 0);
-
-		while (InternetReadFile (hResource, buffer, 1023, &dwRead))
-		{
-			if (dwRead == 0)
-			{
-				break;
-			}
-			buffer[dwRead] = 0;
-		}
-
-		HttpQueryInfo(hResource,
-					HTTP_QUERY_STATUS_CODE,
-					&infobuffer,
-					&infolen,
-					NULL);
-
-		InternetCloseHandle (hResource);
-		InternetCloseHandle (hConnect);
-		InternetCloseHandle (hOpen);
-
-		statuscode = atoi(infobuffer);
-		if (statuscode == 200)
-			return buffer;
-		else
-			return "Unknown";
-	}
-}
-
-static int
-print_version (char *word[], char *word_eol[], void *userdata)
-{
-	char *version;
-	int prevbuf;
-	int convbuf;
-
-	if (!g_ascii_strcasecmp ("HELP", word[2]))
-	{
-		hexchat_printf (ph, "%s", upd_help);
-		return HEXCHAT_EAT_HEXCHAT;
-	}
-	else if (!g_ascii_strcasecmp ("SET", word[2]))
-	{
-		if (!g_ascii_strcasecmp ("", word_eol[4]))
-		{
-			hexchat_printf (ph, "%s\tEnter a value!\n", name);
-			return HEXCHAT_EAT_HEXCHAT;
-		}
-		if (!g_ascii_strcasecmp ("delay", word[3]))
-		{
-			convbuf = atoi (word[4]);	/* don't use word_eol, numbers must not contain spaces */
-
-			if (convbuf > 0 && convbuf < INT_MAX)
-			{
-				prevbuf = hexchat_pluginpref_get_int (ph, "delay");
-				hexchat_pluginpref_set_int (ph, "delay", convbuf);
-				hexchat_printf (ph, "%s\tUpdate check startup delay is set to %d seconds (from %d).\n", name, convbuf, prevbuf);
-			}
-			else
-			{
-				hexchat_printf (ph, "%s\tInvalid input!\n", name);
-			}
-		}
-		else if (!g_ascii_strcasecmp ("freq", word[3]))
-		{
-			convbuf = atoi (word[4]);	/* don't use word_eol, numbers must not contain spaces */
-
-			if (convbuf > 0 && convbuf < INT_MAX)
-			{
-				prevbuf = hexchat_pluginpref_get_int (ph, "freq");
-				hexchat_pluginpref_set_int (ph, "freq", convbuf);
-				hexchat_printf (ph, "%s\tUpdate check frequency is set to %d minutes (from %d).\n", name, convbuf, prevbuf);
-			}
-			else
-			{
-				hexchat_printf (ph, "%s\tInvalid input!\n", name);
-			}
-		}
-		else
-		{
-			hexchat_printf (ph, "%s\tInvalid variable name! Use 'delay' or 'freq'!\n", name);
-			return HEXCHAT_EAT_HEXCHAT;
-		}
-
-		return HEXCHAT_EAT_HEXCHAT;
-	}
-	else if (!g_ascii_strcasecmp ("", word[2]))
-	{
-		version = check_version ();
-
-		if (strcmp (version, hexchat_get_info (ph, "version")) == 0)
-		{
-			hexchat_printf (ph, "%s\tYou have the latest version of HexChat installed!\n", name);
-		}
-		else if (strcmp (version, "Unknown") == 0)
-		{
-			hexchat_printf (ph, "%s\tUnable to check for HexChat updates!\n", name);
-		}
-		else
-		{
-#ifdef _WIN64 /* use this approach, the wProcessorArchitecture method always returns 0 (=x86) for some reason */
-			hexchat_printf (ph, "%s:\tA HexChat update is available! You can download it from here:\n%s/HexChat%%20%s%%20x64.exe\n", name, DOWNLOAD_URL, version);
-#else
-			hexchat_printf (ph, "%s:\tA HexChat update is available! You can download it from here:\n%s/HexChat%%20%s%%20x86.exe\n", name, DOWNLOAD_URL, version);
-#endif
-		}
-		return HEXCHAT_EAT_HEXCHAT;
-	}
-	else
-	{
-		hexchat_printf (ph, "%s", upd_help);
-		return HEXCHAT_EAT_HEXCHAT;
-	}
-}
-
-static int
-print_version_quiet (void *userdata)
-{
-	char *version = check_version ();
-
-	/* if it's not the current version AND not network error */
-	if (!(strcmp (version, hexchat_get_info (ph, "version")) == 0) && !(strcmp (version, "Unknown") == 0))
-	{
-#ifdef _WIN64 /* use this approach, the wProcessorArchitecture method always returns 0 (=x86) for plugins for some reason */
-		hexchat_printf (ph, "%s\tA HexChat update is available! You can download it from here:\n%s/HexChat%%20%s%%20x64.exe\n", name, DOWNLOAD_URL, version);
-#else
-		hexchat_printf (ph, "%s\tA HexChat update is available! You can download it from here:\n%s/HexChat%%20%s%%20x86.exe\n", name, DOWNLOAD_URL, version);
-#endif
-		/* print update url once, then stop the timer */
-		return 0;
-	}
-	/* keep checking */
-	return 1;
-}
+static char version[] = "5.0";
+static const char upd_help[] = "Update Checker Usage:\n  /UPDCHK, check for HexChat updates\n";
 
 static int
-delayed_check (void *userdata)
+check_cmd (char *word[], char *word_eol[], void *userdata)
 {
-	int freq = hexchat_pluginpref_get_int (ph, "freq");
+	win_sparkle_check_update_with_ui ();
 
-	/* only start the timer if there's no update available during startup */
-	if (print_version_quiet (NULL))
-	{
-		/* check for updates, every 6 hours by default */
-		hexchat_hook_timer (ph, freq * 1000 * 60, print_version_quiet, NULL);
-	}
-
-	return 0;	/* run delayed_check() only once */
+	return HEXCHAT_EAT_ALL;
 }
 
 int
 hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
 {
-	int delay;
 	ph = plugin_handle;
 
 	*plugin_name = name;
 	*plugin_desc = desc;
 	*plugin_version = version;
 
-	/* these are required for the very first run */
-	delay = hexchat_pluginpref_get_int (ph, "delay");
-	if (delay == -1)
-	{
-		delay = DEFAULT_DELAY;
-		hexchat_pluginpref_set_int (ph, "delay", DEFAULT_DELAY);
-	}
-
-	if (hexchat_pluginpref_get_int (ph, "freq") == -1)
-	{
-		hexchat_pluginpref_set_int (ph, "freq", DEFAULT_FREQ);
-	}
+	win_sparkle_set_appcast_url (APPCAST_URL);
+	win_sparkle_init ();
 
-	hexchat_hook_command (ph, "UPDCHK", HEXCHAT_PRI_NORM, print_version, upd_help, NULL);
-	hexchat_hook_timer (ph, delay * 1000, delayed_check, NULL);
+	hexchat_hook_command (ph, "UPDCHK", HEXCHAT_PRI_NORM, check_cmd, upd_help, NULL);
 	hexchat_command (ph, "MENU -ishare\\download.png ADD \"Help/Check for Updates\" \"UPDCHK\"");
 	hexchat_printf (ph, "%s plugin loaded\n", name);
 
-	return 1;       /* return 1 for success */
+	return 1;
 }
 
 int
 hexchat_plugin_deinit (void)
 {
+	win_sparkle_cleanup ();
+
 	hexchat_command (ph, "MENU DEL \"Help/Check for updates\"");
 	hexchat_printf (ph, "%s plugin unloaded\n", name);
 	return 1;
diff --git a/plugins/upd/upd.vcxproj b/plugins/upd/upd.vcxproj
index e7e7785a..e39a2887 100644
--- a/plugins/upd/upd.vcxproj
+++ b/plugins/upd/upd.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>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,80 +20,33 @@
     <RootNamespace>upd</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</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>

-    <TargetName>hcupd</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcupd</TargetName>

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

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

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UPD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UPD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>..\..\src\common;$(WinSparklePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>upd.def</ModuleDefinitionFile>

-      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(DepLibs);WinSparkle.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(WinSparklePath);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

     </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;UPD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;$(Glib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>..\..\src\common;$(WinSparklePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>upd.def</ModuleDefinitionFile>

-      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(DepLibs);WinSparkle.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(WinSparklePath);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

@@ -102,6 +56,4 @@
     <ClCompile Include="upd.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

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

diff --git a/plugins/winamp/winamp.c b/plugins/winamp/winamp.c
index 389adcbc..d8788164 100644
--- a/plugins/winamp/winamp.c
+++ b/plugins/winamp/winamp.c
@@ -13,6 +13,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <glib.h>
 
 #include "hexchat-plugin.h"
 
@@ -21,163 +22,127 @@
 
 static hexchat_plugin *ph;   /* plugin handle */
 
-BOOL winamp_found = FALSE;
-
-int status = 0;
-
-/* Slightly modified from X-Chat's log_escape_strcpy */
-static char *
-song_strcpy (char *dest, char *src)
+static int
+winamp(char *word[], char *word_eol[], void *userdata)
 {
-	while (*src)
-	{
-		*dest = *src;
-		dest++;
-		src++;
+	HWND hwndWinamp = FindWindowW(L"Winamp v1.x",NULL);
 
-		if (*src == '%')
+	if (hwndWinamp)
+	{
+		if (!stricmp("PAUSE", word[2]))
 		{
-			dest[0] = '%';
-			dest++;
+			if (SendMessage(hwndWinamp,WM_USER, 0, 104))
+			{
+				SendMessage(hwndWinamp, WM_COMMAND, 40046, 0);
+			
+				if (SendMessage(hwndWinamp, WM_USER, 0, 104) == PLAYING)
+					hexchat_printf(ph, "Winamp: playing");
+				else
+					hexchat_printf(ph, "Winamp: paused");
+			}
 		}
-	}
-
-	dest[0] = 0;
-	return dest - 1;
-}
-
-static int
-winamp(char *word[], char *word_eol[], void *userdata)
-{
+		else if (!stricmp("STOP", word[2]))
+		{
+			SendMessage(hwndWinamp, WM_COMMAND, 40047, 0);
+			hexchat_printf(ph, "Winamp: stopped");
+		}
+		else if (!stricmp("PLAY", word[2]))
+		{
+			SendMessage(hwndWinamp, WM_COMMAND, 40045, 0);
+			hexchat_printf(ph, "Winamp: playing");
+		}
+		else if (!stricmp("NEXT", word[2]))
+		{
+			SendMessage(hwndWinamp, WM_COMMAND, 40048, 0);
+			hexchat_printf(ph, "Winamp: next playlist entry");
+		}
+		else if (!stricmp("PREV", word[2]))
+		{
+			SendMessage(hwndWinamp, WM_COMMAND, 40044, 0);
+			hexchat_printf(ph, "Winamp: previous playlist entry");
+		}
+		else if (!stricmp("START", word[2]))
+		{
+			SendMessage(hwndWinamp, WM_COMMAND, 40154, 0);
+			hexchat_printf(ph, "Winamp: playlist start");
+		}
+		else if (!word_eol[2][0])
+		{
+			wchar_t wcurrent_play[2048];
+			char *current_play, *p;
+			int len = GetWindowTextW(hwndWinamp, wcurrent_play, G_N_ELEMENTS(wcurrent_play));
 
-char current_play[2048], *p;
-char p_esc[2048];
-char cur_esc[2048];
-char truc[2048];
-HWND hwndWinamp = FindWindow("Winamp v1.x",NULL);
+			current_play = g_utf16_to_utf8 (wcurrent_play, len, NULL, NULL, NULL);
+			if (!current_play)
+			{
+				hexchat_print (ph, "Winamp: Error getting song information.");
+				return HEXCHAT_EAT_ALL;
+			}
 
-    if (hwndWinamp)
-	{
-	    {
-	        if (!stricmp("PAUSE", word[2]))
+			if (strchr(current_play, '-'))
 			{
-			   if (SendMessage(hwndWinamp,WM_USER, 0, 104))
+				/* Remove any trailing text and whitespace */
+				p = current_play + strlen(current_play) - 8;
+				while (p >= current_play)
 				{
-			   	   SendMessage(hwndWinamp, WM_COMMAND, 40046, 0);
-			
-			       if (SendMessage(hwndWinamp, WM_USER, 0, 104) == PLAYING)
-			   	       hexchat_printf(ph, "Winamp: playing");
-			       else
-                       hexchat_printf(ph, "Winamp: paused");
+					if (!strnicmp(p, "- Winamp", 8))
+						break;
+					p--;
 				}
-            }
-			else
-		        if (!stricmp("STOP", word[2]))
-			    {
-			       SendMessage(hwndWinamp, WM_COMMAND, 40047, 0);
-			       hexchat_printf(ph, "Winamp: stopped");
-			    }
-			else
-			    if (!stricmp("PLAY", word[2]))
-			    {
-			         SendMessage(hwndWinamp, WM_COMMAND, 40045, 0);
-			         hexchat_printf(ph, "Winamp: playing");
-			    }
-        	else
-
-			    if (!stricmp("NEXT", word[2]))
-			    {
-			         SendMessage(hwndWinamp, WM_COMMAND, 40048, 0);
-			         hexchat_printf(ph, "Winamp: next playlist entry");
-			    }
-			else
 
-                if (!stricmp("PREV", word[2]))
-			    {
-			         SendMessage(hwndWinamp, WM_COMMAND, 40044, 0);
-			         hexchat_printf(ph, "Winamp: previous playlist entry");
-			    }
-		    else
-
-                if (!stricmp("START", word[2]))
-			    {
-			         SendMessage(hwndWinamp, WM_COMMAND, 40154, 0);
-			         hexchat_printf(ph, "Winamp: playlist start");
-			    }
-
-		    else
-
-                if (!word_eol[2][0])
-			    {
-					GetWindowText(hwndWinamp, current_play, sizeof(current_play));
-
-					if (strchr(current_play, '-'))
-					{
-	
-					p = current_play + strlen(current_play) - 8;
-					while (p >= current_play)
-					{
-						if (!strnicmp(p, "- Winamp", 8)) break;
-							p--;
-					}
-
-					if (p >= current_play) p--;
-	
-					while (p >= current_play && *p == ' ') p--;
-						*++p=0;
-	
-	
-					p = strchr(current_play, '.') + 1;
-
- 					song_strcpy(p_esc, p);
- 					song_strcpy(cur_esc, current_play);
-	
-					if (p)
-					{
-						sprintf(truc, "me is now playing:%s", p_esc);
-					}
-					else
-					{
-						sprintf(truc, "me is now playing:%s", cur_esc);
-					}
-	
-	   				hexchat_commandf(ph, truc);
-	
-				}
-				else hexchat_print(ph, "Winamp: Nothing being played.");
+				if (p >= current_play)
+					p--;
+
+				while (p >= current_play && *p == ' ')
+					p--;
+				*++p = '\0';
+
+				/* Ignore any leading track number */
+				p = strstr (current_play, ". ");
+				if (p)
+					p += 2;
+				else
+					p = current_play;
+
+				if (*p != '\0')
+					hexchat_commandf (ph, "me is now playing: %s", p);
+				else
+					hexchat_print (ph, "Winamp: No song information found.");
+				g_free (current_play);
 			}
-		    else
-                hexchat_printf(ph, "Usage: /WINAMP [PAUSE|PLAY|STOP|NEXT|PREV|START]\n");
-         }
-
+			else
+				hexchat_print(ph, "Winamp: Nothing being played.");
+		}
+		else
+			hexchat_printf(ph, "Usage: /WINAMP [PAUSE|PLAY|STOP|NEXT|PREV|START]\n");
 	}
 	else
 	{
-       hexchat_print(ph, "Winamp not found.\n");
+		hexchat_print(ph, "Winamp not found.\n");
 	}
 	return HEXCHAT_EAT_ALL;
 }
 
 int
 hexchat_plugin_init(hexchat_plugin *plugin_handle,
-                      char **plugin_name,
-                      char **plugin_desc,
-                      char **plugin_version,
-                      char *arg)
+					  char **plugin_name,
+					  char **plugin_desc,
+					  char **plugin_version,
+					  char *arg)
 {
 	/* we need to save this for use with any hexchat_* functions */
 	ph = plugin_handle;
 
 	*plugin_name = "Winamp";
 	*plugin_desc = "Winamp plugin for HexChat";
-	*plugin_version = "0.5";
+	*plugin_version = "0.6";
 
 	hexchat_hook_command (ph, "WINAMP", HEXCHAT_PRI_NORM, winamp, "Usage: /WINAMP [PAUSE|PLAY|STOP|NEXT|PREV|START] - control Winamp or show what's currently playing", 0);
    	hexchat_command (ph, "MENU -ishare\\music.png ADD \"Window/Display Current Song (Winamp)\" \"WINAMP\"");
 
 	hexchat_print (ph, "Winamp plugin loaded\n");
 
-	return 1;       /* return 1 for success */
+	return 1;	   /* return 1 for success */
 }
 
 int
diff --git a/plugins/winamp/winamp.vcxproj b/plugins/winamp/winamp.vcxproj
index 3c0cfb34..cf839cfa 100644
--- a/plugins/winamp/winamp.vcxproj
+++ b/plugins/winamp/winamp.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>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,76 +20,31 @@
     <RootNamespace>winamp</RootNamespace>

   </PropertyGroup>

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

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

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </PropertyGroup>

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

-    <ConfigurationType>DynamicLibrary</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>

-    <TargetName>hcwinamp</TargetName>

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

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

-  </PropertyGroup>

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

-    <LinkIncremental>false</LinkIncremental>

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

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

+  <PropertyGroup>

     <TargetName>hcwinamp</TargetName>

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

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

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WINAMP_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

-    <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <ModuleDefinitionFile>winamp.def</ModuleDefinitionFile>

-    </Link>

   </ItemDefinitionGroup>

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

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;WINAMP_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup>

+    <ClCompile>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>winamp.def</ModuleDefinitionFile>

+      <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

@@ -98,6 +54,4 @@
     <ClCompile Include="winamp.c" />

   </ItemGroup>

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

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

 </Project>
\ No newline at end of file